Remove the goimpl and move it to a separate branch

This commit is contained in:
Sameer Rahmani 2021-04-13 13:47:13 +01:00
parent 202f041515
commit 38089606c1
76 changed files with 1 additions and 6666 deletions

View File

@ -38,7 +38,7 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
set(CMAKE_CXX_FLAGS_RELEASE
"${CMAKE_CXX_FLAGS_RELEASE} -O3")
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/scripts/cmake")
set(MemoryCheckCommand "valgrind")
add_compile_options(-fno-rtti)

23
Jenkinsfile vendored
View File

@ -1,23 +0,0 @@
pipeline {
agent any
stages {
stage('Build') {
steps {
sh("make build")
echo 'Building..'
sh("make clean")
}
}
stage('Test') {
steps {
echo 'Testing..'
}
}
stage('Deploy') {
steps {
echo 'Deploying....'
}
}
}
}

View File

@ -1,14 +0,0 @@
ROOT_DIR=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
include $(ROOT_DIR)/bootstrap/Makefile
.PHONY: lint
lint: lint-bootstrap
.PHONY: compile
compile: compile-bootstrap
.PHONY: build
build: compile
clean: clean-bootstrap

View File

@ -1,101 +0,0 @@
linters-settings:
dupl:
threshold: 100
funlen:
lines: 100
statements: 50
gci:
local-prefixes: github.com/udemy/schema-vault
goconst:
min-len: 2
min-occurrences: 2
gocritic:
enabled-tags:
- diagnostic
- experimental
- opinionated
- performance
- style
disabled-checks:
- dupImport
- ifElseChain
- octalLiteral
- whyNoLint
- wrapperFunc
settings:
rangeValCopy:
sizeThreshold: 512
gocyclo:
min-complexity: 15
goimports:
local-prefixes: github.com/udemy/schema-vault
golint:
min-confidence: 0
gomnd:
settings:
mnd:
checks: argument,return
govet:
check-shadowing: true
maligned:
suggest-new: true
misspell:
locale: US
nolintlint:
allow-leading-space: true
allow-unused: false
require-explanation: false
require-specific: false
linters:
disable-all: true
enable:
- bodyclose
- deadcode
- depguard
- dogsled
- dupl
- errcheck
- funlen
- gochecknoinits
- goconst
- gocritic
- gocyclo
- goimports
- gofmt
- golint
- gomnd
- goprintffuncname
- gosec
- gosimple
- govet
- ineffassign
- interfacer
- misspell
- nakedret
- noctx
- nolintlint
- rowserrcheck
- scopelint
- staticcheck
- structcheck
- stylecheck
- typecheck
- unconvert
- unparam
- unused
- varcheck
- whitespace
issues:
exclude-rules:
- path: _test\.go
linters:
- gomnd
- linters:
- gocritic
text: "unnecessaryDefer:"
run:
timeout: 1m
issues-exit-code: 1
tests: true
skip-dirs-use-default: true
allow-parallel-runners: true

View File

@ -1,13 +0,0 @@
FROM golang:1-alpine
LABEL maintainer="Sameer Rahmani <lxsameer@gnu.org>"
RUN mkdir -p /usr/src/serene
WORKDIR /usr/src/serene
COPY go.mod go.sum ./
RUN go mod download -x
COPY . .
# Build the Go app
RUN go build -v ./serene.go
CMD ["./serene"]

View File

@ -1,339 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -1,11 +0,0 @@
BOOTSTRAP_TAG ?= latest
BOOTSTRAP_DIR = $(ROOT_DIR)/bootstrap
compile-bootstrap:
docker build -t serene-lang/serene-bootstrap:$(BOOTSTRAP_TAG) $(BOOTSTRAP_DIR)
clean-bootstrap:
docker rmi serene-lang/serene-bootstrap:$(BOOTSTRAP_TAG)
lint-bootstrap:
docker run --rm -v $(BOOTSTRAP_DIR):/app -w /app golangci/golangci-lint:v1.35.2 golangci-lint run pkg/core

View File

@ -1,50 +0,0 @@
#+OPTIONS: num:t toc:nil
* Serene lang (Bootstrap interpreter)
The bootstrap version of Serene is used to bootstrap the compiler which is written in Serene
itself. It's an interpreter with minimal set of features and rough edges.
#+TOC: headlines 2
** Heads up
Since the interpreter is there to bootstrap the compiler the goal is to keep it simple and good enough
too run the compiler. So we don't want to over engineer things because the interpreter will go away
evantually. Here is the list of things that we implemented ( or will implement ) differently:
- *Normal Macros* (Syntax macro): Since bootstrap version is an interpreter we don't have clear
distinction between compile time and runtime (We have only runtime) - unless we build bytecode support
into the interpreter to be able to cache the compiled ast - So we can't really implemeent normal macros
as they meant to be implemented.
- List implementation: We don't follow the actual list implementation as a single or doubly linked
list. So far we kept it really stupid by creating a wrapper around Go slices. But we need to fix this
one in the future.
- Since we didn't write the reader in Serene itself, there is no reader macroes.
** New contributors
If you're a new contributor and you want to start working on the source code and don't know where to start,
just look through the source code for *TODO:* sections and the ~dev.org~ on the root for some higher level
TODOs.
In order to start reading the code start from the ~pkg/core/parser.go~ file which is the parser implementation
and then take a look at ~pkg/core/core.go~ and ~pkg/core/eval.go~. If you have any question feel free to ask them
either on the mailing list or the gitter/IRC channel.
** Development hint
*** Use Make... functions
In order to create a new value in any type use the designated Make function, for example: =MakeList=
** Setup development environment
*** Emacs
All you have to do is to install =LSP= and =gopls= that's it.
** Running the REPL
In order to run the REPL by compiling the code just do:
#+BEGIN_SRC bash
go run serene.go repl
#+END_SRC
There is a =--debug= parameter which enables more debug output (For example: read -> AST -> out data).

View File

@ -1,39 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cmd
import (
"github.com/spf13/cobra"
"serene-lang.org/bootstrap/pkg/core"
)
// replCmd represents the base command when called without any subcommands
var replCmd = &cobra.Command{
Use: "repl",
Short: "Runs the local Serene's REPL",
Long: `Runs the local Serene's REPL to interact with Serene`,
Run: func(cmd *cobra.Command, args []string) {
// TODO: Get the debug value from a CLI flag
core.REPL(makeFlags())
},
}
func init() { // nolint:gochecknoinits
rootCmd.AddCommand(replCmd)
}

View File

@ -1,80 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Package cmd provides the sub commands for the Serene binary.
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
)
var debugMode bool
var stackDebugMode bool
func makeFlags() map[string]bool {
return map[string]bool{
"debugMode": debugMode,
"stackDebugMode": stackDebugMode,
}
}
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "Serene",
Short: "The bootstrap version",
Long: `Serene's bootstrap interpreter V0.1.0
Serene's bootstrap interpreter is used to
bootstrap the Serene's compiler.'
It comes with ABSOLUTELY NO WARRANTY;
This is free software, and you are welcome
to redistribute it under certain conditions;
for details take a look at the LICENSE file.
`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Fix me!!!! I don't do anything !!!")
},
}
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func init() { // nolint:gochecknoinits
cobra.OnInitialize()
rootCmd.PersistentFlags().BoolVar(
&debugMode,
"debug",
false,
"Turns on the debug mode.")
rootCmd.PersistentFlags().BoolVar(
&stackDebugMode,
"debug-stack",
false,
"Turns on the call stack debug mode.")
}

View File

@ -1,38 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cmd
import (
"github.com/spf13/cobra"
"serene-lang.org/bootstrap/pkg/core"
)
// replCmd represents the base command when called without any subcommands
var runCmd = &cobra.Command{
Use: "run NS",
Short: "Evaluates the given NS and runs the main function of it",
Long: `Evaluates the given NS and runs the main function`,
Run: func(cmd *cobra.Command, args []string) {
core.Run(makeFlags(), args)
},
}
func init() { // nolint:gochecknoinits
rootCmd.AddCommand(runCmd)
}

View File

@ -1,16 +0,0 @@
(ns examples.ffi.foo
:require '[adssa
[serene.ffi.libllvm]])
(defmacro deffi.....)
(ffi/deffi some-function
:fn-name "some_function"
:args {:x :i32
:y :char_ptr}
:return :void)
(some-function 12 "asdasd")

View File

@ -1,5 +0,0 @@
foo:
gcc -c -Wall -Werror -fpic foo.c
gcc -shared -o libfoo.so foo.o
all: foo

View File

@ -1,7 +0,0 @@
#include <stdio.h>
void bar(void)
{
puts("Hello, I am a shared library");
}

View File

@ -1,6 +0,0 @@
#ifndef foo_h__
#define foo_h__
extern void baz(void);
#endif // foo_h__

Binary file not shown.

Binary file not shown.

View File

@ -1,25 +0,0 @@
(ns examples.hello-world)
(def hello-world
(fn (name)
(println "hello" name)))
(def a1
(fn (x y)
x))
(defmacro defn
(name args &body)
(list 'do
(list 'def name (cons 'fn (list args body)))))
(defn pp (x y)
(asd)
(println x))
(macroexpand '(pp 33 22))
(def main
(fn ()
(pp "sam" 2)
(hello-world "world")))

View File

@ -1,12 +0,0 @@
module serene-lang.org/bootstrap
go 1.15
require (
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
github.com/golangci/golangci-lint v1.35.2 // indirect
github.com/gookit/color v1.3.5
github.com/rjeczalik/pkgconfig v0.0.0-20190903131546-94d388dab445
github.com/spf13/cobra v1.1.1
github.com/spf13/viper v1.7.1
)

View File

@ -1,637 +0,0 @@
4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a h1:wFEQiK85fRsEVF0CRrPAos5LoAryUsIX1kPW/WrIqFw=
4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Djarvur/go-err113 v0.0.0-20200511133814-5174e21577d5 h1:XTrzB+F8+SpRmbhAH8HLxhiiG6nYNwaBZjrFps1oWEk=
github.com/Djarvur/go-err113 v0.0.0-20200511133814-5174e21577d5/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OpenPeeDeeP/depguard v1.0.1 h1:VlW4R6jmBIv3/u1JNlawEvJMM4J+dPORPaZasQee8Us=
github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/antlr/antlr4 v0.0.0-20201029161626-9a95f0cc3d7c h1:j/C2kxPfyE0d87/ggAjIsCV5Cdkqmjb+O0W8W+1J+IY=
github.com/antlr/antlr4 v0.0.0-20201029161626-9a95f0cc3d7c/go.mod h1:T7PbCXFs94rrTttyxjbyT5+/1V8T2TYDejxUfHJjw1Y=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/ashanbrown/forbidigo v1.0.0 h1:QdNXBduDUopc3GW+YVYZn8jzmIMklQiCfdN2N5+dQeE=
github.com/ashanbrown/forbidigo v1.0.0/go.mod h1:PH+zMRWE15yW69fYfe7Kn8nYR6yYyafc3ntEGh2BBAg=
github.com/ashanbrown/makezero v0.0.0-20201205152432-7b7cdbb3025a h1:/U9tbJzDRof4fOR51vwzWdIBsIH6R2yU0KG1MBRM2Js=
github.com/ashanbrown/makezero v0.0.0-20201205152432-7b7cdbb3025a/go.mod h1:oG9Dnez7/ESBqc4EdrdNlryeo7d0KcW1ftXHm7nU/UU=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/bombsimon/wsl/v3 v3.1.0 h1:E5SRssoBgtVFPcYWUOFJEcgaySgdtTNYzsSKDOY7ss8=
github.com/bombsimon/wsl/v3 v3.1.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/daixiang0/gci v0.2.8 h1:1mrIGMBQsBu0P7j7m1M8Lb+ZeZxsZL+jyGX4YoMJJpg=
github.com/daixiang0/gci v0.2.8/go.mod h1:+4dZ7TISfSmqfAGv59ePaHfNzgGtIkHAhhdKggP1JAc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denis-tingajkin/go-header v0.4.2 h1:jEeSF4sdv8/3cT/WY8AgDHUoItNSoEZ7qg9dX7pc218=
github.com/denis-tingajkin/go-header v0.4.2/go.mod h1:eLRHAVXzE5atsKAnNRDB90WHCFFnBUn4RN0nRcs1LJA=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-critic/go-critic v0.5.3 h1:xQEweNxzBNpSqI3wotXZAixRarETng3PTG4pkcrLCOA=
github.com/go-critic/go-critic v0.5.3/go.mod h1:2Lrs1m4jtOnnG/EdezbSpAoL0F2pRW+9HWJUZ+QaktY=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g=
github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4=
github.com/go-toolsmith/astcopy v1.0.0 h1:OMgl1b1MEpjFQ1m5ztEO06rz5CUd3oBv9RF7+DyvdG8=
github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ=
github.com/go-toolsmith/astequal v1.0.0 h1:4zxD8j3JRFNyLN46lodQuqz3xdKSrur7U/sr0SDS/gQ=
github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY=
github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k=
github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw=
github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU=
github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg=
github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI=
github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc=
github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4=
github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
github.com/go-toolsmith/typep v1.0.2 h1:8xdsa1+FSIH/RhEkgnD1j2CJOy5mNllW1Q9tRiYwvlk=
github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b h1:khEcpUM4yFcxg4/FHQWkvVRmgijNXRfzkIDHh23ggEo=
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY=
github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0=
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4=
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM=
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk=
github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6 h1:YYWNAGTKWhKpcLLt7aSj/odlKrSrelQwlovBpDuf19w=
github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0=
github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613 h1:9kfjN3AdxcbsZBf8NjltjWihK2QfBBBZuv91cMFfDHw=
github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8=
github.com/golangci/gocyclo v0.0.0-20180528144436-0a533e8fa43d h1:pXTK/gkVNs7Zyy7WKgLXmpQ5bHTrq5GDsp8R9Qs67g0=
github.com/golangci/gocyclo v0.0.0-20180528144436-0a533e8fa43d/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU=
github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a h1:iR3fYXUjHCR97qWS8ch1y9zPNsgXThGwjKPrYfqMPks=
github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU=
github.com/golangci/golangci-lint v1.35.2 h1:hD1999/sq3tCPXhhI4UpunxpAAdH9pK7kDIObqoGuWA=
github.com/golangci/golangci-lint v1.35.2/go.mod h1:Sg5fFp5oLLI1B8gXfUVUSePju8XF0uWefMkuZuGIHUo=
github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc h1:gLLhTLMk2/SutryVJ6D4VZCU3CUqr8YloG7FPIBWFpI=
github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU=
github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA=
github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg=
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA=
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o=
github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770 h1:EL/O5HGrF7Jaq0yNhBLucz9hTuRzj2LdwGBOaENgxIk=
github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA=
github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21 h1:leSNB7iYzLYSSx3J/s5sVf4Drkc68W2wm4Ixh/mr0us=
github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI=
github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0 h1:HVfrLniijszjS1aiNg8JbBMO2+E1WIQ+j/gL4SQqGPg=
github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4=
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys=
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gookit/color v1.3.1/go.mod h1:R3ogXq2B9rTbXoSHJ1HyUVAZ3poOJHpd9nQmyGZsfvQ=
github.com/gookit/color v1.3.5 h1:1nszcmDVrfti1Su5fhtuS5YBs/Xs6v8UIi0bJ/2oDHY=
github.com/gookit/color v1.3.5/go.mod h1:GqqLKF1le3EfrbHbYsYa5WdLqfc/PHMdMRbt6tMnqIc=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw=
github.com/gostaticanalysis/analysisutil v0.4.1 h1:/7clKqrVfiVwiBQLM0Uke4KvXnO6JcCTS7HwF2D6wG8=
github.com/gostaticanalysis/analysisutil v0.4.1/go.mod h1:18U/DLpRgIUd459wGxVHE0fRgmo1UgHDcbw7F5idXu0=
github.com/gostaticanalysis/comment v1.3.0/go.mod h1:xMicKDx7XRXYdVwY9f9wQpDJVnqWxw9wCauCMKp+IBI=
github.com/gostaticanalysis/comment v1.4.1 h1:xHopR5L2lRz6OsjH4R2HG5wRhW9ySl3FsHIvi5pcXwc=
github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jgautheron/goconst v0.0.0-20201117150253-ccae5bf973f3 h1:7nkB9fLPMwtn/R6qfPcHileL/x9ydlhw8XyDrLI1ZXg=
github.com/jgautheron/goconst v0.0.0-20201117150253-ccae5bf973f3/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4=
github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a h1:GmsqmapfzSJkm28dhRoHz2tLRbJmqhU86IPgBtN3mmk=
github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a/go.mod h1:xRskid8CManxVta/ALEhJha/pweKBaVG6fWgc0yH25s=
github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3 h1:jNYPNLe3d8smommaoQlK7LOA5ESyUJJ+Wf79ZtA7Vp4=
github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0=
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
github.com/jmoiron/sqlx v1.2.1-0.20190826204134-d7d95172beb5/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kulti/thelper v0.2.1 h1:H4rSHiB3ALx//SXr+k9OPqKoOw2cAZpIQwVNH1RL5T4=
github.com/kulti/thelper v0.2.1/go.mod h1:vMu2Cizjy/grP+jmsvOFDx1kYP6+PD1lqg4Yu5exl2U=
github.com/kunwardeep/paralleltest v1.0.2 h1:/jJRv0TiqPoEy/Y8dQxCFJhD56uS/pnvtatgTZBHokU=
github.com/kunwardeep/paralleltest v1.0.2/go.mod h1:ZPqNm1fVHPllh5LPVujzbVz1JN2GhLxSfY+oqUsvG30=
github.com/kyoh86/exportloopref v0.1.8 h1:5Ry/at+eFdkX9Vsdw3qU4YkvGtzuVfzT4X7S77LoN/M=
github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/maratori/testpackage v1.0.1 h1:QtJ5ZjqapShm0w5DosRjg0PRlSdAdlx+W6cCKoALdbQ=
github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU=
github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb h1:RHba4YImhrUVQDHUCe2BNSOz4tVy2yGyXhvYDvxGgeE=
github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mbilski/exhaustivestruct v1.1.0 h1:4ykwscnAFeHJruT+EY3M3vdeP8uXMh0VV2E61iR7XD8=
github.com/mbilski/exhaustivestruct v1.1.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/moricho/tparallel v0.2.1 h1:95FytivzT6rYzdJLdtfn6m1bfFJylOJK41+lgv/EHf4=
github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k=
github.com/mozilla/tls-observatory v0.0.0-20200317151703-4fa42e1c2dee/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nakabonne/nestif v0.3.0 h1:+yOViDGhg8ygGrmII72nV9B/zGxY188TYpfolntsaPw=
github.com/nakabonne/nestif v0.3.0/go.mod h1:dI314BppzXjJ4HsCnbo7XzrJHPszZsjnk5wEBSYHI2c=
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E=
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nishanths/exhaustive v0.1.0 h1:kVlMw8h2LHPMGUVqUj6230oQjjTMFjwcZrnkhXzFfl8=
github.com/nishanths/exhaustive v0.1.0/go.mod h1:S1j9110vxV1ECdCudXRkeMnFQ/DQk9ajLT0Uf2MYZQQ=
github.com/nishanths/predeclared v0.2.1 h1:1TXtjmy4f3YCFjTxRd8zcFHOmoUir+gp0ESzjFzG2sw=
github.com/nishanths/predeclared v0.2.1/go.mod h1:HvkGJcA3naj4lOwnFXFDkFxVtSqQMB9sbB1usJ+xjQE=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d h1:CdDQnGF8Nq9ocOS/xlSptM1N3BbrA6/kmaep5ggwaIA=
github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/polyfloyd/go-errorlint v0.0.0-20201127212506-19bd8db6546f h1:xAw10KgJqG5NJDfmRqJ05Z0IFblKumjtMeyiOLxj3+4=
github.com/polyfloyd/go-errorlint v0.0.0-20201127212506-19bd8db6546f/go.mod h1:wi9BfjxjF/bwiZ701TzmfKu6UKC357IOAtNr0Td0Lvw=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
github.com/quasilyte/go-ruleguard v0.2.1-0.20201030093329-408e96760278 h1:5gcJ7tORNCNB2QjOJF+MYjzS9aiWpxhP3gntf7RVrOQ=
github.com/quasilyte/go-ruleguard v0.2.1-0.20201030093329-408e96760278/go.mod h1:2RT/tf0Ce0UDj5y243iWKosQogJd8+1G3Rs2fxmlYnw=
github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 h1:L8QM9bvf68pVdQ3bCFZMDmnt9yqcMBro1pC7F+IPYMY=
github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0=
github.com/rjeczalik/pkgconfig v0.0.0-20190903131546-94d388dab445 h1:HTpnmNOc0MiWqyJqaiKRO3paZOCo+JqGaDN9ZMKy57w=
github.com/rjeczalik/pkgconfig v0.0.0-20190903131546-94d388dab445/go.mod h1:TmjBR6hcDoH9/baYY27h9m2Qk2obtYgLAwgGGvsuwPA=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryancurrah/gomodguard v1.2.0 h1:YWfhGOrXwLGiqcC/u5EqG6YeS8nh+1fw0HEc85CVZro=
github.com/ryancurrah/gomodguard v1.2.0/go.mod h1:rNqbC4TOIdUDcVMSIpNNAzTbzXAZa6W5lnUepvuMMgQ=
github.com/ryanrolds/sqlclosecheck v0.3.0 h1:AZx+Bixh8zdUBxUA1NxbxVAS78vTPq4rCb8OUZI9xFw=
github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/securego/gosec/v2 v2.5.0 h1:kjfXLeKdk98gBe2+eYRFMpC4+mxmQQtbidpiiOQ69Qc=
github.com/securego/gosec/v2 v2.5.0/go.mod h1:L/CDXVntIff5ypVHIkqPXbtRpJiNCh6c6Amn68jXDjo=
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU=
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs=
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sonatard/noctx v0.0.1 h1:VC1Qhl6Oxx9vvWo3UDgrGXYCeKCe3Wbw7qAWL6FrmTY=
github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI=
github.com/sourcegraph/go-diff v0.6.1 h1:hmA1LzxW0n1c3Q4YbrFgg4P99GSnebYa3x8gr0HZqLQ=
github.com/sourcegraph/go-diff v0.6.1/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/ssgreg/nlreturn/v2 v2.1.0 h1:6/s4Rc49L6Uo6RLjhWZGBpWWjfzk2yrf1nIW8m4wgVA=
github.com/ssgreg/nlreturn/v2 v2.1.0/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tdakkota/asciicheck v0.0.0-20200416190851-d7f85be797a2 h1:Xr9gkxfOP0KQWXKNqmwe8vEeSUiUj4Rlee9CMVX2ZUQ=
github.com/tdakkota/asciicheck v0.0.0-20200416190851-d7f85be797a2/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM=
github.com/tetafro/godot v1.3.2 h1:HzWC3XjadkyeuBZxkfAFNY20UVvle0YD51I6zf6RKlU=
github.com/tetafro/godot v1.3.2/go.mod h1:ah7jjYmOMnIjS9ku2krapvGQrFNtTLo9Z/qB3dGU1eU=
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e h1:RumXZ56IrCj4CL+g1b9OL/oH0QnsF976bC8xQFYUD5Q=
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tomarrell/wrapcheck v0.0.0-20200807122107-df9e8bcb914d h1:3EZyvNUMsGD1QA8cu0STNn1L7I77rvhf2IhOcHYQhSw=
github.com/tomarrell/wrapcheck v0.0.0-20200807122107-df9e8bcb914d/go.mod h1:yiFB6fFoV7saXirUGfuK+cPtUh4NX/Hf5y2WC2lehu0=
github.com/tommy-muehle/go-mnd v1.3.1-0.20201008215730-16041ac3fe65 h1:Y0bLA422kvb32uZI4fy/Plop/Tbld0l9pSzl+j1FWok=
github.com/tommy-muehle/go-mnd v1.3.1-0.20201008215730-16041ac3fe65/go.mod h1:T22e7iRN4LsFPZGyRLRXeF+DWVXFuV9thsyO7NjbbTI=
github.com/ultraware/funlen v0.0.3 h1:5ylVWm8wsNwH5aWo9438pwvsK0QiqVuUrt9bn7S/iLA=
github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
github.com/ultraware/whitespace v0.0.4 h1:If7Va4cM03mpgrNH9k49/VOicWpGoG70XPBFFODYDsg=
github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
github.com/uudashr/gocognit v1.0.1 h1:MoG2fZ0b/Eo7NXoIwCVFLG5JED3qgQz5/NEE+rOsjPs=
github.com/uudashr/gocognit v1.0.1/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA=
github.com/valyala/quicktemplate v1.6.3/go.mod h1:fwPzK2fHuYEODzJ9pkw0ipCPNHZ2tD5KW4lOuSdPKzY=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0 h1:8pl+sMODzuvGJkmj2W4kZihvVb5mKm8pB/X44PIQHv8=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634 h1:bNEHhJCnrwMKNMmOx3yAynp5vs5/gRy+XWFtZFu7NBM=
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190307163923-6a08e3108db3/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190916130336-e45ffcd953cc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200625211823-6506e20df31f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200831203904-5a2aa26beb65/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20201007032633-0806396f153e/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20201011145850-ed2f50202694/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20201030010431-2feb2bb1ff51/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201114224030-61ea331ec02b/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201118003311-bd56c0adb394/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105210202-9ed45478a130 h1:8qSBr5nyKsEgkP918Pu5FFDZpTtLIjXSo6mrtdVOFfk=
golang.org/x/tools v0.0.0-20210105210202-9ed45478a130/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.6 h1:W18jzjh8mfPez+AwGLxmOImucz/IFjpNlrKVnaj2YVc=
honnef.co/go/tools v0.0.1-2020.1.6/go.mod h1:pyyisuGw24ruLjrr1ddx39WE0y9OooInRzEYLhQB2YY=
mvdan.cc/gofumpt v0.1.0 h1:hsVv+Y9UsZ/mFZTxJZuHVI6shSQCtzZ11h1JEFPAZLw=
mvdan.cc/gofumpt v0.1.0/go.mod h1:yXG1r1WqZVKWbVRtBWKWX9+CxGYfA51nSomhM0woR48=
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I=
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo=
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
mvdan.cc/unparam v0.0.0-20200501210554-b37ab49443f7 h1:kAREL6MPwpsk1/PQPFD3Eg7WAQR5mPTWZJaBiG5LDbY=
mvdan.cc/unparam v0.0.0-20200501210554-b37ab49443f7/go.mod h1:HGC5lll35J70Y5v7vCGb9oLhHoScFwkHDJm/05RdSTc=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=

View File

@ -1,44 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Package ast provides the functionality and data structures around the
// Serene's AST.
package ast
type NodeType int
const (
Nil NodeType = iota
Nothing
Bool
Instruction
Symbol
Keyword
Number
List
Fn
NativeFn
Namespace
String
Block // Dont' mistake it with block from other programming languages
)
type ITypable interface {
GetType() NodeType
}

View File

@ -1,116 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ast
// ILocatable describes something that can be located in a source
type ILocatable interface {
GetLocation() *Location
}
// Location is used to point to a specific location in the source
// code (before parse). It can point to a single point or a range.
type Location struct {
start int
end int
// Where this location is pointing too ?
source Source
// Is it a known location or not ? For example builtins doesn't
// have a knowen location
knownLocation bool
}
var UnknownLocation *Location = &Location{knownLocation: false}
func (l *Location) GetStart() int {
return l.start
}
func (l *Location) GetEnd() int {
return l.end
}
// GetSource returns the source of the current location or the "builtin"
// source to indicate that the source of this location is not known in
// the context of source code
func (l *Location) GetSource() *Source {
if l.IsKnownLocaiton() {
return &l.source
}
return GetBuiltinSource()
}
// IncStart increases the start pointer of the location by `x` with respect
// to the boundaries of the source
func (l *Location) IncStart(x int) {
if x+l.start < len(*l.source.Buffer) {
l.start += x
} else {
l.start = len(*l.source.Buffer) - 1
}
}
// DecStart decreases the start pointer of the location by `x` with respect
// to the boundaries of the source
func (l *Location) DecStart(x int) {
if l.start-x >= 0 {
l.start -= x
} else {
l.start = 0
}
}
// IncEnd increases the end pointer of the location by `x` with respect
// to the boundaries of the source
func (l *Location) IncEnd(x int) {
if x+l.end < len(*l.source.Buffer) {
l.end += x
} else {
l.end = len(*l.source.Buffer) - 1
}
}
// DecEnd decreases the end pointer of the location by `x` with respect
// to the boundaries of the source
func (l *Location) DecEnd(x int) {
if l.end-x >= 0 {
l.end -= x
} else {
l.end = 0
}
}
func (l *Location) IsKnownLocaiton() bool {
return l.knownLocation
}
// MakeLocation return a pointer to a `Location` in the given source `input`
// specified by the `start` and `end` boundaries
func MakeLocation(input *Source, start, end int) *Location {
return &Location{
source: *input,
start: start,
end: end,
knownLocation: true,
}
}
func MakeUnknownLocation() *Location {
return UnknownLocation
}

View File

@ -1,97 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ast
// The Source data structure is used to track expression back to the source
// code. For example to find which source (file) they belongs to.
import (
"sort"
"strings"
)
var builtinSource *Source
var OutOfRangeLine string = "----"
type Source struct {
// A Pointer to the buffer where the parser used for parsing the source
Buffer *[]string
// The namespace name which this source is describing
NS string
// This array contains the boundaries of each line in the buffer. For example
// [24 50 106] means that the buffer contains 3 lines and the first line can
// be found from the index 0 to index 24 of the buffer and the second line is
// from index 25 till 50 and so on
LineIndex *[]int
}
// GetSubstr returns the a pointer to the string from the buffer specified by the `start` and `end`
func (s *Source) GetSubstr(start, end int) *string {
if start < len(*s.Buffer) && start >= 0 && end < len(*s.Buffer) && end > 0 && start <= end {
result := strings.Join((*s.Buffer)[start:end], "")
return &result
}
return nil
}
// GetLine returns the line specified by the `linenum` from the buffer. It will return "----" if the
// given line number exceeds the boundaries of the buffer
func (s *Source) GetLine(linenum int) string {
lines := strings.Split(strings.Join(*s.Buffer, ""), "\n")
if linenum > 0 && linenum <= len(lines) {
return lines[linenum-1]
}
return OutOfRangeLine
}
// LineNumberFor returns the line number associated with the given position `pos` in
// the buffer
func (s *Source) LineNumberFor(pos int) int {
if pos < 0 {
return -1
}
result := sort.SearchInts(*s.LineIndex, pos)
// We've found something
if result > -1 {
// Since line numbers start from 1 unlike arrays :))
result++
}
return result
}
// GetBuiltinSource returns a pointer to a source that represents builtin
// expressions
func GetBuiltinSource() *Source {
if builtinSource == nil {
buf := strings.Split("builtin", "")
lineindex := []int{len(buf) - 1}
builtinSource = &Source{
Buffer: &buf,
NS: "Serene.builtins",
LineIndex: &lineindex,
}
}
return builtinSource
}

View File

@ -1,94 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
import (
"fmt"
"strings"
"serene-lang.org/bootstrap/pkg/ast"
"serene-lang.org/bootstrap/pkg/hash"
)
// Block struct represents a group of forms. Don't confuse it with
// code blocks from other languages that specify a block using curly
// brackets and indentation.
// Blocks in serene are just a group of forms and nothing more.
type Block struct {
ExecutionScope
body []IExpr
}
func (b *Block) GetType() ast.NodeType {
return ast.Block
}
func (b *Block) String() string {
var strs []string
for _, e := range b.body {
strs = append(strs, e.String())
}
return strings.Join(strs, " ")
}
func (b *Block) ToDebugStr() string {
return fmt.Sprintf("%#v", b)
}
func (b *Block) GetLocation() *ast.Location {
if len(b.body) > 0 {
return b.body[0].GetLocation()
}
return ast.MakeUnknownLocation()
}
func (b *Block) Hash() uint32 {
bytes := []byte("TODO")
return hash.Of(append([]byte{byte(ast.Block)}, bytes...))
}
func (b *Block) ToSlice() []IExpr {
return b.body
}
func (b *Block) SetContent(body []IExpr) {
b.body = body
}
// Append the given expr `form` to the block
func (b *Block) Append(form IExpr) {
b.body = append(b.body, form)
}
func (b *Block) Count() int {
return len(b.body)
}
// MakeEmptyBlock creates an empty block
func MakeEmptyBlock() *Block {
return &Block{}
}
// MakeBlock creates a block that holds the given array of
// forms `body`.
func MakeBlock(body []IExpr) *Block {
return &Block{
body: body,
}
}

View File

@ -1,66 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
import (
"serene-lang.org/bootstrap/pkg/ast"
"serene-lang.org/bootstrap/pkg/hash"
)
type Bool struct {
Node
ExecutionScope
value bool
}
func (t *Bool) GetType() ast.NodeType {
return ast.Bool
}
func (t *Bool) String() string {
if t.value {
return TRUEFORM
}
return FALSEFORM
}
func (t *Bool) ToDebugStr() string {
return t.String()
}
func (t *Bool) Hash() uint32 {
bytes := []byte(t.String())
return hash.Of(append([]byte{byte(ast.Bool)}, bytes...))
}
func (t *Bool) IsTrue() bool {
return t.value
}
func (t *Bool) IsFalse() bool {
return !t.value
}
func MakeTrue(n Node) *Bool {
return &Bool{Node: n, value: true}
}
func MakeFalse(n Node) *Bool {
return &Bool{Node: n, value: false}
}

View File

@ -1,87 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
// BUILTINS is used in the Runtime to support builtin functions of
// the language which are implemented in Go
var BUILTINS = map[string]NativeFunction{
"pr": MakeNativeFn("pr", PrNativeFn),
"prn": MakeNativeFn("prn", PrnNativeFn),
"print": MakeNativeFn("print", PrintNativeFn),
"println": MakeNativeFn("println", PrintlnNativeFn),
"require": MakeNativeFn("require", RequireNativeFn),
"hash": MakeNativeFn("hash", HashNativeFn),
}
func PrNativeFn(rt *Runtime, scope IScope, n Node, args *List) (IExpr, IError) {
Pr(rt, toRepresentables(args.Rest().(IColl))...)
return MakeNil(n), nil
}
func PrnNativeFn(rt *Runtime, scope IScope, n Node, args *List) (IExpr, IError) {
Prn(rt, toRepresentables(args.Rest().(IColl))...)
return MakeNil(n), nil
}
func PrintNativeFn(rt *Runtime, scope IScope, n Node, args *List) (IExpr, IError) {
Print(rt, toRepresentables(args.Rest().(IColl))...)
return MakeNil(n), nil
}
func PrintlnNativeFn(rt *Runtime, scope IScope, n Node, args *List) (IExpr, IError) {
Println(rt, toRepresentables(args.Rest().(IColl))...)
return MakeNil(n), nil
}
func RequireNativeFn(rt *Runtime, scope IScope, n Node, args *List) (IExpr, IError) {
switch args.Count() {
case 0:
return nil, MakeError(rt, args, "'require' function is missing")
case 1:
return nil, MakeError(rt, args.First(), "'require' function needs at least one argument")
default:
}
var result IExpr
var err IError
for _, ns := range args.Rest().(*List).ToSlice() {
result, err = RequireNamespace(rt, ns)
if err != nil {
return nil, err
}
}
return result, nil
}
func HashNativeFn(rt *Runtime, scope IScope, n Node, args *List) (IExpr, IError) {
if args.Count() != 2 {
return nil, MakeError(rt, args.First(), "'hash' function needs exactly one argument")
}
expr := args.Rest().First()
result, err := MakeInteger(expr.Hash())
if err != nil {
return nil, err
}
result.Node = n
return result, nil
}

View File

@ -1,191 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
// CallStack implementation:
// * A callstack should be FIFA stack
// * It should keep track of function calls.
// * Anything that implements `IFn` can be tracked by the call stack
// * Since Serene uses eval loop to eliminate tail calls we need
// the call stack to be able to track recursive calls. For
// now by just counting number of calls to a functions that is already
// in the stack.
//
// TODOs:
// * At the moment if we call the same function twice (not as a recursive)
// function call stack will record it as a recursive call. We need
// compare the stack items by their address, identity and location.
// * Add support for iteration on the stack.
import (
"fmt"
)
type ICallStack interface {
// Push the given callable `f` to the stack
Push(f IFn) IError
Pop() *Frame
Peek() *Frame
Count() uint
}
type Frame struct {
// Number of recursive calls to this function
Count uint
// Function to call
Callee IFn
// Where is the call happening
Caller IExpr
}
type TraceBack = []*Frame
type CallStackItem struct {
prev *CallStackItem
data Frame
}
type CallStack struct {
debug bool
head *CallStackItem
count uint
}
func (f *Frame) String() string {
return fmt.Sprintf("<Frame: FN: %s, Count: %d Caller: \n%s\n>", f.Callee, f.Count, f.Caller)
}
func (c *CallStack) Count() uint {
return c.count
}
func (c *CallStack) GetCurrentFn() IFn {
if c.head == nil {
return nil
}
return c.head.data.Callee
}
func (c *CallStack) Push(caller IExpr, f IFn) IError {
if c.debug {
fmt.Println("[Stack] -->", f)
}
if f == nil {
return MakePlainError("Can't push 'nil' pointer to the call stack.")
}
if caller == nil {
return MakePlainError("Can't push 'nil' pointer to the call stack for the caller.")
}
// Empty Stack
if c.head == nil {
c.head = &CallStackItem{
data: Frame{
Callee: f,
Caller: caller,
Count: 0,
},
}
c.count++
}
nodeData := &c.head.data
// If the same function was on top of the stack
if nodeData.Callee == f && caller == nodeData.Caller {
// TODO: expand the check here to support address and location as well
nodeData.Count++
} else {
c.head = &CallStackItem{
prev: c.head,
data: Frame{
Callee: f,
Caller: caller,
Count: 0,
},
}
c.count++
}
return nil
}
func (c *CallStack) Pop() *Frame {
if c.head == nil {
if c.debug {
fmt.Println("[Stack] <-- nil")
}
return nil
}
result := c.head
c.head = result.prev
c.count--
if c.debug {
fmt.Printf("[Stack] <-- %s\n", result.data.Callee)
}
return &result.data
}
func (c *CallStack) Peek() *Frame {
if c.head == nil {
if c.debug {
fmt.Println("[Stack] <-- nil")
}
return nil
}
result := c.head
return &result.data
}
func (c *CallStack) ToTraceBack() *TraceBack {
var tr TraceBack
item := c.head
for {
if item == nil {
break
}
// TODO: This doesn't seem efficient. Fix it.
tr = append([]*Frame{&item.data}, tr...)
item = item.prev
}
return &tr
}
func MakeCallStack(debugMode bool) CallStack {
return CallStack{
count: 0,
head: nil,
debug: debugMode,
}
}
func MakeFrame(rt *Runtime, caller IExpr, f IFn, count uint) *Frame {
return &Frame{
Count: count,
Caller: caller,
Callee: f,
}
}

View File

@ -1,37 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
// ISeq is an interface describing a sequence of forms
type ISeq interface {
First() IExpr
Rest() ISeq
}
type ICountable interface {
Count() int
}
// IColl describes a collection of values. A finite collection.
type IColl interface {
ISeq
ICountable
ToSlice() []IExpr
Cons(e IExpr) IExpr
}

View File

@ -1,24 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
const NSFORM string = "ns"
const NILFORM string = "nil"
const FALSEFORM string = "false"
const TRUEFORM string = "true"

View File

@ -1,171 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Package core contains the high level internal function of Serene
package core
import (
"bytes"
"fmt"
"html/template"
"os"
"path/filepath"
"github.com/chzyer/readline"
)
type mainRunner struct {
NS string
Args string
}
func rep(rt *Runtime, line string) {
ast, err := ReadString("serene.internal", line)
if err != nil {
PrintError(rt, err)
return
}
// Debug data, ugly right ? :))
if rt.IsDebugMode() {
fmt.Printf("[DEBUG] Parsed AST: %s\n", ast.String())
}
result, e := Eval(rt, ast)
if e != nil {
PrintError(rt, e)
return
}
Prn(rt, result)
}
/** TODO:
Replace the readline implementation with go-prompt.
*/
// REPL executes a Read Eval Print Loop locally reading from stdin and
// writing to stdout
func REPL(flags map[string]bool) {
cwd, err := os.Getwd()
if err != nil {
panic(err)
}
rt := MakeRuntime([]string{cwd}, flags)
rt.CreateNS("user", "REPL", true)
rl, err := readline.NewEx(&readline.Config{
Prompt: "> ",
HistoryFile: filepath.Join(os.Getenv("HOME"), ".serene.history"),
InterruptPrompt: "^C",
EOFPrompt: "exit",
HistorySearchFold: true,
})
if err != nil {
panic(err)
}
rl.HistoryEnable()
defer rl.Close()
fmt.Print(`
_______ _______ ______ _______ _______ _______
| __| ___| __ \ ___| | | ___|
|__ | ___| < ___| | ___|
|_______|_______|___|__|_______|__|____|_______|
Serene's bootstrap interpreter is used to
bootstrap the Serene's compiler.
It comes with ABSOLUTELY NO WARRANTY;
This is free software, and you are welcome
to redistribute it under certain conditions;
for details take a look at the LICENSE file.\n\n
`)
for {
rl.SetPrompt(fmt.Sprintf("%s> ", rt.CurrentNS().GetName()))
line, err := rl.Readline()
if err != nil { // io.EOF
break
}
rep(rt, line)
}
}
func Run(flags map[string]bool, args []string) {
cwd, e := os.Getwd()
if e != nil {
panic(e)
}
rt := MakeRuntime([]string{cwd}, flags)
rt.CreateNS("serene.internal", "RUN", true)
if len(args) == 0 {
PrintError(rt, MakePlainError("'run' command needs at least one argument"))
os.Exit(1)
}
var buf bytes.Buffer
arguments := ""
ns := args[0]
if len(args) > 1 {
for _, arg := range args[1:] {
arguments += "\"" + arg + "\""
}
}
tmpl, e := template.New("run").Parse(
`(require '({{.NS}} n))
(n/main {{.Args}})`,
)
if e != nil {
panic(e)
}
e = tmpl.Execute(&buf, &mainRunner{ns, arguments})
if e != nil {
panic(e)
}
if rt.IsDebugMode() {
fmt.Println("[DEBUG] Evaluating the following form to run the 'main' fn:")
fmt.Println(buf.String())
}
ast, err := ReadString("serene.internal", buf.String())
if err != nil {
PrintError(rt, err)
os.Exit(1)
}
_, err = Eval(rt, ast)
if err != nil {
PrintError(rt, err)
return
}
}

View File

@ -1,186 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
// Error implementations:
// * `IError` is the main interface to represent errors.
// * `Error` struct is an expression itself.
// * `IError` and any implementation of it has to implement `ILocatable`
// so we can point to the exact location of the error.
// * We have to use `IError` everywhere and avoid using Golangs errors
// since IError is an expression itself.
//
// TODOs:
// * Make errors stackable, so different pieces of code can stack related
// errors on top of each other so user can track them through the code
// * Errors should contain a help message as well to give some hints to the
// user about how to fix the problem. Something similar to Rust's error
// messages
// * Integrate the call stack with IError
import (
"fmt"
"serene-lang.org/bootstrap/pkg/ast"
"serene-lang.org/bootstrap/pkg/errors"
)
type ErrType uint8
const (
SyntaxError ErrType = iota
SemanticError
RuntimeError
)
func (e ErrType) String() string {
return [...]string{"Syntax Error", "Semantic Error", "Runtime Error"}[e]
}
// IError defines the necessary functionality of the internal errors.
type IError interface {
// In order to point to a specific point in the input
ast.ILocatable
// We want errors to be printable by the `print` family
IRepresentable
IDebuggable
GetErrType() ErrType
GetErrno() errors.Errno
GetDescription() *string
GetStackTrace() *TraceBack
// To wrap Golan rrrrors
WithError(err error) IError
// Some errors might doesn't have any node available to them
// at the creation time. SetNode allows us to the the appropriate
// node later in time.
SetNode(n *Node)
}
type Error struct {
Node
errtype ErrType
errno errors.Errno
WrappedErr error
msg string
trace *TraceBack
}
func (e *Error) String() string {
return e.msg
}
func (e *Error) ToDebugStr() string {
_, isInternalErr := e.WrappedErr.(*Error)
if isInternalErr {
return fmt.Sprintf("%s:\n\t%s", e.msg, e.WrappedErr.(*Error).ToDebugStr())
}
return fmt.Sprintf("%s:\n\t%s", e.msg, e.WrappedErr.Error())
}
func (e *Error) GetErrType() ErrType {
return e.errtype
}
func (e *Error) WithError(err error) IError {
e.WrappedErr = err
return e
}
func (e *Error) SetNode(n *Node) {
e.Node = *n
}
func (e *Error) Error() string {
return e.msg
}
func (e *Error) GetStackTrace() *TraceBack {
return e.trace
}
func (e *Error) GetErrno() errors.Errno {
return e.errno
}
func (e *Error) GetDescription() *string {
desc, ok := errors.ErrorsDescription[e.errno]
if ok {
return &desc
}
desc = errors.ErrorsDescription[0]
return &desc
}
func MakePlainError(msg string) IError {
return &Error{
msg: msg,
}
}
// MakeError creates an Error which points to the given IExpr `e` as
// the root of the error.
func MakeError(rt *Runtime, e IExpr, msg string) IError {
rt.Stack.Push(e, rt.Stack.GetCurrentFn())
return &Error{
Node: MakeNodeFromExpr(e),
errtype: RuntimeError,
msg: msg,
trace: rt.Stack.ToTraceBack(),
}
}
func MakeRuntimeError(rt *Runtime, e IExpr, errno errors.Errno, msg string) IError {
rt.Stack.Push(e, rt.Stack.GetCurrentFn())
return &Error{
Node: MakeNodeFromExpr(e),
errtype: RuntimeError,
msg: msg,
errno: errno,
trace: rt.Stack.ToTraceBack(),
}
}
func MakeSyntaxErrorf(n Node, msg string, a ...interface{}) IError {
return &Error{
Node: n,
errtype: SyntaxError,
msg: fmt.Sprintf(msg, a...),
}
}
func MakeSemanticError(rt *Runtime, e IExpr, errno errors.Errno, msg string) IError {
rt.Stack.Push(e, rt.Stack.GetCurrentFn())
frames := &[]*Frame{
rt.Stack.Pop(),
}
return &Error{
Node: MakeNodeFromExpr(e),
errtype: SemanticError,
errno: errno,
msg: msg,
trace: frames,
}
}

View File

@ -1,689 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
import (
"fmt"
"serene-lang.org/bootstrap/pkg/ast"
"serene-lang.org/bootstrap/pkg/errors"
)
func restOfExprs(es []IExpr, i int) []IExpr {
if len(es)-1 > i {
return es[i+1:]
}
return []IExpr{}
}
// evalForm evaluates the given expression `form` by a slightly different
// evaluation rules. For example if `form` is a list instead of the formal
// evaluation of a list it will evaluate all the elements and return the
// evaluated list
func evalForm(rt *Runtime, scope IScope, form IExpr) (IExpr, IError) { //nolint:gocyclo
switch form.GetType() {
case ast.Nil:
return form, nil
case ast.Number:
return form, nil
case ast.Fn:
return form, nil
case ast.String:
return form, nil
// Keyword evaluation rules:
// * Keywords evaluates to themselves with respect to a
// possible namespace alias. For example `::core/xyz`
// will evaluates to `:serene.core/xyz` only if the ns
// `serene.core` is loaded in the current ns with the
// `core` alias. Also `::xyz` will evaluete to
// `:<CURRENT_NS>/xyz`
case ast.Keyword:
// Eval initialize the keyword and MUTATES the state of the keyword
// and returns the updated keyword which would be the same
return form.(*Keyword).Eval(rt, scope)
// Symbol evaluation rules:
// * If it's a NS qualified symbol (NSQS), Look it up in the external symbol table of
// the current namespace.
// * If it's not a NSQS Look up the name in the current scope.
// * Otherwise throw an error
case ast.Symbol:
var nsName string
sym := form.(*Symbol)
symbolName := sym.GetName()
switch symbolName {
case TRUEFORM:
return MakeTrue(MakeNodeFromExpr(form)), nil
case FALSEFORM:
return MakeFalse(MakeNodeFromExpr(form)), nil
case NILFORM:
return MakeNil(MakeNodeFromExpr(form)), nil
default:
var expr *Binding
ns := scope.GetNS(rt)
if sym.IsNSQualified() {
// Whether a namespace with the given alias loaded or not
if !ns.hasExternal(sym.GetNSPart()) {
return nil, MakeError(rt, sym,
fmt.Sprintf("Namespace '%s' is no loaded", sym.GetNSPart()),
)
}
expr = ns.LookupGlobal(rt, sym)
nsName = sym.GetNSPart()
} else {
expr = scope.Lookup(rt, symbolName)
nsName = ns.GetName()
}
if expr == nil {
return nil, MakeRuntimeError(
rt,
sym,
errors.E0003,
fmt.Sprintf(
"can't resolve symbol '%s' in ns '%s'",
symbolName,
nsName,
),
)
}
return expr.Value, nil
}
// Evaluate all the elements in the list instead of following the lisp convention
case ast.List:
var result []IExpr
lst := form.(*List)
for {
if lst.Count() > 0 {
expr, err := EvalForms(rt, scope, lst.First())
if err != nil {
return nil, err
}
result = append(result, expr)
lst = lst.Rest().(*List)
} else {
break
}
}
return MakeList(MakeNodeFromExpr(lst), result), nil
}
// Default case
return nil, MakeError(rt, form, fmt.Sprintf("support for '%d' is not implemented", form.GetType()))
}
// EvalForms evaluates the given expr `expressions` (it can be a list, block, symbol or anything else)
// with the given runtime `rt` and the scope `scope`.
func EvalForms(rt *Runtime, scope IScope, expressions IExpr) (IExpr, IError) { //nolint:funlen,gocyclo
// EvalForms is the main and the most important evaluation function on Serene.
// It's a long loooooooooooong function. Why? Well, Because we don't want to
// waste call stack spots in order to have a well organized code.
// In order to avoid stackoverflows and implement TCO ( which is a must for
// a functional language we need to avoid unnecessary calls and keep as much
// as possible in a loop.
//
// `expressions` is argument is basically a tree of expressions which
// this function walks over and rewrite it as necessary. The main purpose
// of rewriting the tree is to eliminate any unnecessary function call.
// This way we can eliminate tail calls and run everything faster.
//
// Execution scopes are just regular scopes that are attached to expressions
// in order to specify the scope that they need to get executed in. Since
// we rewrite the tree some of the nodes of the tree (expressions) has different
// scope so we need to attach a scope to those expressions. An example would be
// the `let` special form. It creates a new scope for its body, after creating
// the scope we will attach it to all the expressions in the body and rewrite
// the tree to replace the original `let` node with the expressions from the
// body of `let` and reloop over the tree. So the tree contains some nodes
// from the `let` body with an execution scope and the rest of tree with
// no execution scope (no attached scope) which we will use the `scope`
// that we got as an argument.
var ret IExpr
var err IError
tco:
// TODO: With the new tree rewrite we might be able to get ride of this `for`
for {
// The TCO loop is there to take advantage or the fact that
// in order to call a function or a block we simply can change
// the value of the `expressions` and `scope`
var exprs []IExpr
// Block evaluation rules:
// * If empty, return Nothing
// * Otherwise evaluate the expressions in the block one by one
// and return the last result
if expressions.GetType() == ast.Block {
if expressions.(*Block).Count() == 0 {
return &Nothing, nil
}
exprs = expressions.(*Block).ToSlice()
} else {
exprs = []IExpr{expressions}
}
body:
for i := 0; i < len(exprs); i++ {
forms := exprs[i]
executionScope := forms.GetExecutionScope()
scope := scope
if executionScope != nil {
scope = executionScope
}
if rt.IsDebugMode() {
fmt.Printf("[DEBUG] Evaluating forms in NS: %s, Forms: %s\n", scope.GetNS(rt).GetName(), forms)
fmt.Printf("[DEBUG] * State: I: %d, Exprs: %s\n", i, exprs)
}
// Evaluate any internal instruction that has to be run.
// Instructions should change the return value, but errors
// are ok
if forms.GetType() == ast.Instruction {
e := ProcessInstruction(rt, forms.(*Instruction))
if e != nil {
return nil, e
}
continue
}
// Evaluating forms one by one
if forms.GetType() != ast.List {
ret, err = evalForm(rt, scope, forms)
if err != nil {
return nil, err
}
continue body
}
// Expand macroes that exists in the given array of expression `forms`.
// Since this implementation of Serene is an interpreter, the line
// between compile time and runtime is unclear (afterall every thing
// is happening in runtime). So we need to expand macroes before evaluating
// other forms. In the future we might want to cache the expanded AST
// as a cache and some sort of a bytecode for faster evaluation.
forms, err = macroexpand(rt, scope, forms)
if err != nil {
return nil, err
}
if forms.GetType() != ast.List {
return evalForm(rt, scope, forms)
}
list := forms.(*List)
// Empty list evaluates to itself
if list.Count() == 0 {
ret = list
break tco // return &Nil, nil here
}
rawFirst := list.First()
sform := ""
// Handling special forms by looking up the first
// element of the list. If it is a symbol, Grab
// the name and check it for build it forms.
//
// Note: If we don't care about recursion in any
// case we can simply extract it to a function
// for example in `def` since we are going to
// evaluate the value separately, we don't care
// about recursion because we're going to handle
// it wen we're evaluating the value. But in the
// case of let it's a different story.
if rawFirst.GetType() == ast.Symbol {
sform = rawFirst.(*Symbol).GetName()
}
switch sform {
// `ns` evaluation rules:
// * The first element has to be a symbol representing the
// name of the namespace. ( We won't evaluate the first
// element )
// TODO: decide on the syntax and complete the docs
case NSFORM:
// TODO: Move this to a native function
ret, err = NSForm(rt, scope, list)
if err != nil {
return nil, err
}
continue body // no rewrite
// `quote` evaluation rules:
// * Only takes one argument
// * Returns the argument without evaluating it
case "quote":
// Including the `quote` itself
if list.Count() != 2 {
return nil, MakeError(rt, list, "'quote' quote only accepts one argument.")
}
ret = list.Rest().First()
err = nil
continue body // no rewrite
// case "quasiquote-expand":
// return quasiquote(list.Rest().First()), nil
// // For `quasiquote` evaluation rules, check out the documentation on
// // the `quasiquote` function in `quasiquote.go`
// case "quasiquote":
// expressions = quasiquote(list.Rest().First())
// continue tco // Loop over to execute the new expressions
// TODO: Implement `list` in serene itself when we have destructuring available
// Creates a new list form it's arguments.
case "list":
ret, err = evalForm(rt, scope, list.Rest().(*List))
if err != nil {
return nil, err
}
continue body // no rewrite
// TODO: Implement `concat` in serene itself when we have protocols available
// Concats all the collections together.
case "concat":
evaledForms, e := evalForm(rt, scope, list.Rest().(*List))
if e != nil {
return nil, e
}
lists := evaledForms.(*List).ToSlice()
result := []IExpr{}
for _, lst := range lists {
if lst.GetType() != ast.List {
return nil, MakeError(rt, lst, fmt.Sprintf("don't know how to concat '%s'", lst.String()))
}
result = append(result, lst.(*List).ToSlice()...)
}
n := MakeNodeFromExprs(result)
if n == nil {
n = &list.Node
}
node := *n
ret, err = MakeList(node, result), nil
if err != nil {
return nil, err
}
continue body // no rewrite
// TODO: Implement `list` in serene itself when we have destructuring available
// Calls the `Cons` function on the second argument to cons the first arg to it.
// In terms of a list, cons adds the first argument to as the new head of the list
// given in the second argument.
case "cons":
if list.Count() != 3 {
return nil, MakeError(rt, list, "'cons' needs exactly 3 arguments")
}
evaledForms, e := evalForm(rt, scope, list.Rest().(*List))
if e != nil {
return nil, e
}
coll, ok := evaledForms.(*List).Rest().First().(IColl)
if !ok {
return nil, MakeError(rt, list, "second arg of 'cons' has to be a collection")
}
ret, err = coll.Cons(evaledForms.(*List).First()), nil
if err != nil {
return nil, err
}
continue body // no rewrite
// `def` evaluation rules
// * The first argument has to be a symbol.
// * The second argument has to be evaluated and be used as
// the value.
// * Defines a global binding in the current namespace using
// the symbol name binded to the value
case "def":
ret, err = Def(rt, scope, list.Rest().(*List))
if err != nil {
return nil, err
}
continue body // no rewrite
// `defmacro` evaluation rules:
// * The first argument has to be a symbol
// * The second argument has to be a list of argument for the macro
// * The rest of the arguments will form a block that acts as the
// body of the macro.
case "defmacro":
ret, err = DefMacro(rt, scope, list)
if err != nil {
return nil, err
}
continue body // no rewrite
// `macroexpand` evaluation rules:
// * It has to have only one argument
// * It WILL evaluate the only argument and tries to expand it
// as a macro and returns the expanded forms.
case "macroexpand":
if list.Count() != 2 {
return nil, MakeError(rt, list, "'macroexpand' needs exactly one argument.")
}
evaledForm, e := evalForm(rt, scope, list.Rest().(*List))
if e != nil {
return nil, e
}
ret, err = macroexpand(rt, scope, evaledForm.(*List).First())
if err != nil {
return nil, err
}
continue body // no rewrite
// `fn` evaluation rules:
// * It needs at least a collection of arguments
// * Defines an anonymous function.
case "fn":
ret, err = Fn(rt, scope, list)
if err != nil {
return nil, err
}
continue body // no rewrite
// `if` evaluation rules:
// * It has to get only 3 arguments: PRED THEN ELSE
// * Evaluate only the PRED expression if the result
// is not `nil` or `false` evaluates THEN otherwise
// evaluate the ELSE expression and return the result.
case "if":
args := list.Rest().(*List)
if args.Count() != 3 {
return nil, MakeError(rt, args, "'if' needs exactly 3 aruments")
}
pred, e := EvalForms(rt, scope, args.First())
result := pred.GetType()
if e != nil {
return nil, e
}
if (result == ast.Bool && pred.(*Bool).IsFalse()) || result == ast.Nil {
// Falsy clause
exprs = append([]IExpr{args.Rest().Rest().First()}, restOfExprs(exprs, i)...)
} else {
// Truthy clause
exprs = append([]IExpr{args.Rest().First()}, restOfExprs(exprs, i)...)
}
i = 0
goto body // rewrite
// `do` evaluation rules:
// * Evaluate the body as a new block in the TCO loop
// and return the result of the last expression
case "do":
// create a new slice of expressions by using the
// do body and merging it by the remaining expressions
// in the old `exprs` value and loop over it
doExprs := list.Rest().(*List).ToSlice()
exprs = append(doExprs, exprs[i+1:]...)
i = 0
goto body // rewrite
// TODO: Implement `eval` as a native function
// `eval` evaluation rules:
// * It only takes on arguments.
// * The argument has to be a form. For example if we pass a string
// to it as an argument that contains some expressions it will
// evaluate the string as string which will result to the same
// string. So IT DOES NOT READ the argument.
// * It will evaluate the given form as the argument and return
// the result.
case "eval":
if list.Count() != 2 {
return nil, MakeError(rt, list, "'eval' needs exactly 1 arguments")
}
form, e := evalForm(rt, scope, list.Rest().(*List))
if e != nil {
return nil, e
}
ret, err = EvalForms(rt, scope, form)
if err != nil {
return nil, err
}
continue body // no rewrite
// `let` evaluation rules:
// Let's assume the following:
// L = (let (A B C D) BODY)
// * Create a new scope which has the current scope as the parent
// * Evaluate the bindings by evaluating `B` and bind it to the name `A`
// in the scope.
// * Repeat the prev step for expr D and name C
// * Eval the block `BODY` using the created scope and return the result
// which is the result of the last expre in `BODY`
case "let":
if list.Count() < 2 {
return nil, MakeError(rt, list, "'let' needs at list 1 aruments")
}
letScope := MakeScope(rt, scope.(*Scope), nil)
// Since we're using IColl for the bindings, we can use either lists
// or vectors or even hashmaps for bindings
var bindings IColl
bindings = list.Rest().First().(IColl)
body := list.Rest().Rest().(*List).ToSlice()
if bindings.Count()%2 != 0 {
return nil, MakeError(rt, list.Rest().First(), "'let' bindings has to have even number of forms.")
}
for {
// We're reducing over bindings here
if bindings.Count() == 0 {
break
}
name := bindings.First()
expr := bindings.Rest().First()
// TODO: We need to destruct the bindings here and remove this check
// for the symbol type
if name.GetType() != ast.Symbol {
return nil, MakeError(rt, name, "'let' doesn't support desbbtructuring yet, use a symbol.")
}
// You might be wondering why we're using `EvalForms` here to evaluate
// the exprs in bindings, what about TCO ?
// Well, It's called TAIL call optimization for a reason. Exprs in the
// bindings are not tail calls
evaluatedExpr, e := EvalForms(rt, letScope, expr)
if e != nil {
return nil, e
}
letScope.Insert(name.String(), evaluatedExpr, false)
bindings = bindings.Rest().Rest().(IColl)
}
changeExecutionScope(body, letScope)
exprs = append(body, exprs[i+1:]...)
i = 0
goto body
// list evaluation rules:
// * The first element of the list has to be an expression which is callable
// * An empty list evaluates to itself.
default:
// Evaluating all the elements of the list
listExprs, e := evalForm(rt, scope, list)
if e != nil {
return nil, e
}
f := listExprs.(*List).First()
switch f.GetType() {
case ast.Fn:
// If the first element of the evaluated list is a function
// create a scope for it by creating the binding to the given
// parameters in the new scope and set the parent of it to
// the scope which the function defined in and then set the
// `expressions` to the body of function and loop again
fn := f.(*Function)
if e != nil {
return nil, e
}
argList := listExprs.(*List).Rest().(*List)
fnScope, e := MakeFnScope(rt, fn.GetScope(), fn.GetParams(), argList)
if e != nil {
return nil, e
}
rt.Stack.Push(list, fn)
body := append(
fn.GetBody().ToSlice(),
// Add the PopStack instruction to clean up the stack after
// returning from the function.
MakeStackPop(rt),
)
changeExecutionScope(body, fnScope)
body = append(body, restOfExprs(exprs, i)...)
exprs = body // Just because of the stupid linters
goto body // rewrite
// If the function was a native function which is represented
// by the `NativeFunction` struct
case ast.NativeFn:
fn := f.(*NativeFunction)
rt.Stack.Push(list, fn)
ret, err = fn.Apply(
rt,
scope,
MakeNodeFromExpr(fn),
listExprs.(*List),
)
if err != nil {
return nil, err
}
rt.Stack.Pop()
continue body // no rewrite
default:
err = MakeError(rt, f, "don't know how to execute anything beside function")
ret = nil
break tco
}
}
}
break tco
}
return ret, err
}
// Eval the given `Block` of code with the given runtime `rt`.
// The Important part here is that any expression that we need
// to Eval has to be wrapped in a Block. Don't confused the
// concept of Block with blocks from other languages which
// specify by using `{}` or indent or what ever. Blocks in terms
// of Serene are just arrays of expressions and nothing more.
func Eval(rt *Runtime, forms *Block) (IExpr, IError) {
if forms.Count() == 0 {
// Nothing is literally Nothing
return &Nothing, nil
}
v, err := EvalForms(rt, rt.CurrentNS().GetRootScope(), forms)
if err != nil {
return nil, err
}
return v, nil
}
// EvalNSBody evals the body of the given namespace `ns` using the given
// runtime `rt`. It makes sure that the body starts with a `ns` special
// form with the same name as the ns argument.
func EvalNSBody(rt *Runtime, ns *Namespace) (*Namespace, IError) {
body := ns.getForms()
exprs := body.ToSlice()
if len(exprs) == 0 {
return nil, MakeSemanticError(
rt,
ns,
errors.E0001,
fmt.Sprintf("the 'ns' form is missing from '%s'", ns.GetName()),
)
}
if exprs[0].GetType() == ast.List {
firstForm := exprs[0].(*List).First()
if firstForm.GetType() == ast.Symbol && firstForm.(*Symbol).GetName() == NSFORM {
_, err := EvalForms(rt, ns.GetRootScope(), body)
if err != nil {
return nil, err
}
return ns, nil
}
}
return nil, MakeError(rt, ns, fmt.Sprintf("the 'ns' form is missing from '%s'", ns.GetName()))
}

View File

@ -1,276 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
// Function implementations:
// * We have two different types of functions. User defined functions and
// native functions
// * User defined functions are represented via the `Function` struct.
// * Native functions are represented via the `NativeFunction` struct.
// * User defined functions gets evaluated by:
// - Creating a new scope a direct child of the scope that the function
// defined in
// - Creating bindings in the new scope to bind the passed values to their
// arguments names
// - Evaluate the body of the function in context of the new scope and return
// the result of the last expression
// * Native functions evaluates by calling the `Apply` method of the `IFn`
// interface which is quite simple.
//
// TODOs:
// * Support for multi-arity functions
// * Support for protocol functions
// * `IFn` protocol
import (
"fmt"
"serene-lang.org/bootstrap/pkg/ast"
"serene-lang.org/bootstrap/pkg/errors"
"serene-lang.org/bootstrap/pkg/hash"
)
type nativeFnHandler = func(rt *Runtime, scope IScope, n Node, args *List) (IExpr, IError)
type IFn interface {
IExpr
Apply(rt *Runtime, scope IScope, n Node, args *List) (IExpr, IError)
GetName() string
}
// Function struct represent a user defined function.
type Function struct {
// Node struct holds the necessary functions to make
// Functions locatable
Node
ExecutionScope
// Name of the function, it can be empty and it has to be
// set via `def`
name string
// Parent scope of the function. The scope which the function
// is defined in
scope IScope
// A collection of arguments. Why IColl? because we can use
// Lists and Vectors for the argument lists. Maybe even
// hashmaps in future.
params IColl
// A reference to the body block of the function
body *Block
isMacro bool
}
type NativeFunction struct {
// Node struct holds the necessary functions to make
// Functions locatable
Node
ExecutionScope
name string
fn nativeFnHandler
}
func (f *Function) GetType() ast.NodeType {
return ast.Fn
}
func (f *Function) Hash() uint32 {
// TODO: Fix this function to return an appropriate hash for a function
return hash.Of([]byte(f.String()))
}
func (f *Function) IsMacro() bool {
return f.isMacro
}
func (f *Function) String() string {
if f.isMacro {
return fmt.Sprintf("<Macro: %s at %p>", f.name, f)
}
return fmt.Sprintf("<Fn: %s at %p>", f.name, f)
}
func (f *Function) GetName() string {
// TODO: Handle ns qualified symbols here
return f.name
}
func (f *Function) SetName(name string) {
f.name = name
}
func (f *Function) GetScope() IScope {
return f.scope
}
func (f *Function) GetParams() IColl {
return f.params
}
func (f *Function) ToDebugStr() string {
if f.isMacro {
return fmt.Sprintf("<Macro: %s at %p>", f.name, f)
}
return fmt.Sprintf("<Fn: %s at %p>", f.name, f)
}
func (f *Function) GetBody() *Block {
return f.body
}
func (f *Function) Apply(rt *Runtime, scope IScope, n Node, args *List) (IExpr, IError) {
application := args.Cons(f)
return EvalForms(rt, scope, application)
}
// MakeFunction Create a function with the given `params` and `body` in
// the given `scope`.
func MakeFunction(n Node, scope IScope, params IColl, body *Block) *Function {
return &Function{
Node: n,
scope: scope,
params: params,
body: body,
isMacro: false,
}
}
// MakeFnScope a new scope for the body of a function. It binds the `bindings`
// to the given `values`.
func MakeFnScope(rt *Runtime, parent IScope, bindings, values IColl) (*Scope, IError) { //nolint:gocyclo
// TODO: Break this function into smaller functions
scope := MakeScope(rt, parent.(*Scope), nil)
// TODO: Implement destructuring
binds := bindings.ToSlice()
exprs := values.ToSlice()
numberOfBindings := len(binds)
if len(binds) > 0 {
lastBinding := binds[len(binds)-1]
if lastBinding.GetType() == ast.Symbol && lastBinding.(*Symbol).IsRestable() {
numberOfBindings = len(binds) - 1
}
if lastBinding.GetType() == ast.Symbol && !lastBinding.(*Symbol).IsRestable() && numberOfBindings < len(exprs) {
return nil, MakeSemanticError(
rt,
values.(IExpr),
errors.E0002,
fmt.Sprintf("expected '%d' arguments, got '%d'.", bindings.Count(), values.Count()),
)
}
}
if numberOfBindings > len(exprs) {
if rt.IsDebugMode() {
fmt.Printf("[DEBUG] Mismatch on bindings and values: Bindings: %s, Values: %s\n", bindings, values)
}
return nil, MakeSemanticError(
rt,
values.(IExpr),
errors.E0002,
fmt.Sprintf("expected '%d' arguments, got '%d'.", bindings.Count(), values.Count()),
)
}
for i := 0; i < len(binds); i++ {
// If an argument started with char `&` use it to represent
// rest of values.
//
// for example: `(fn (x y &z) ...)`
if binds[i].GetType() == ast.Symbol && binds[i].(*Symbol).IsRestable() {
if i != len(binds)-1 {
return nil, MakeError(rt, binds[i], "The function argument with '&' has to be the last argument.")
}
// if the number of values are one less than the number of bindings
// but the last binding is a Restable (e.g &x) the the last bindings
// has to be an empty list. Note the check for number of vlaues comes
// next.
rest := MakeEmptyList(MakeNodeFromExpr(binds[i]))
if i <= len(exprs)-1 {
// If the number of values matches the number of bindings
// or it is more than that create a list from them
// to pass it to the last argument that has to be Restable (e.g &x)
elements := exprs[i:]
var node Node
if len(elements) > 0 {
n := MakeNodeFromExprs(elements)
if n == nil {
n = &values.(*List).Node
}
node = *n
} else {
node = MakeNodeFromExpr(binds[i])
}
rest = MakeList(node, elements)
}
scope.Insert(binds[i].(*Symbol).GetName()[1:], rest, false)
break
} else {
scope.Insert(binds[i].(*Symbol).GetName(), exprs[i], false)
}
}
return scope, nil
}
func (f *NativeFunction) GetType() ast.NodeType {
return ast.NativeFn
}
func (f *NativeFunction) GetName() string {
return f.name
}
func (f *NativeFunction) String() string {
return fmt.Sprintf("<NativeFn: %s at %p>", f.name, f)
}
func (f *NativeFunction) Hash() uint32 {
// TODO: Fix this function to return an appropriate hash for a function
return hash.Of([]byte(f.String()))
}
func (f *NativeFunction) ToDebugStr() string {
return fmt.Sprintf("<NativeFn: %s>", f.name)
}
func (f *NativeFunction) Apply(rt *Runtime, scope IScope, n Node, args *List) (IExpr, IError) {
return f.fn(rt, scope, n, args)
}
func MakeNativeFn(name string, f nativeFnHandler) NativeFunction {
return NativeFunction{
Node: MakeNodeFromLocation(ast.MakeUnknownLocation()),
name: name,
fn: f,
}
}

View File

@ -1,91 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
// Instructions Implementation:
// * Instructions are expressions as well but they are not doing
// anything special by themselves.
// * We need them to be expressions because we need to process
// them as part of the evaluation loop
// * We use instructions as nodes in the AST to instruct Serene
// to do specific tasks after rewriting the AST. For example
// `PopStack` instructs Serene to simply pop a call from the
// call stack.
// * Instructions doesn't return a value and should not alter
// the return value of the eval loop. But they might interrupt
// the loop by raising an error `IError`.
import (
"fmt"
"serene-lang.org/bootstrap/pkg/ast"
"serene-lang.org/bootstrap/pkg/hash"
)
type instructionType int
// Instruction types
const (
// Pop a function from the call stack. We use this
// instruction at the end of function bodies. So
// function bodies will clean up after themselves
PopStack instructionType = iota
)
type Instruction struct {
// Just to be compatible with IExpr ---
Node
ExecutionScope
// ------------------------------------
Type instructionType
}
func (n *Instruction) GetType() ast.NodeType {
return ast.Instruction
}
func (n *Instruction) String() string {
return fmt.Sprintf("<instruction:%d>", n.Type)
}
func (n *Instruction) ToDebugStr() string {
return n.String()
}
func (n *Instruction) Hash() uint32 {
bytes := []byte(fmt.Sprintf("%d", n.Type))
return hash.Of(append([]byte{byte(ast.Instruction)}, bytes...))
}
func MakeStackPop(rt *Runtime) IExpr {
return &Instruction{
Type: PopStack,
}
}
// ProcessInstruction is the main function to process instructions
func ProcessInstruction(rt *Runtime, form *Instruction) IError {
switch form.Type {
case PopStack:
rt.Stack.Pop()
return nil
default:
panic(fmt.Sprintf("Unknown instruction: '%d'", form.Type))
}
}

View File

@ -1,220 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
// Keyword implementation:
// IMPORTANT NOTE: This implementation keyword is not decent at all
// it lacks many aspects of keywords which makes them great. But
// it is good enough for our use case. So we'll leave it as it is.
//
// Keywords are simple names and just names and nothing more. They
// match the following grammar:
//
// ```
// KEYWORD = COLON [COLON] SYMBOL
// ```
// Normally keywords doesn't have any namespace for example `:xyz`
// is just a name, but in order to avoid any name collision Serene
// supports namespace qualified keywords which basically put a keyword
// under a namespace. But it doesn't mean that you need to load a
// namespace in order to use any keyword that lives under that ns.
// because keywords are just names remember? There is two ways to
// use namespace qualified keywords:
//
// 1. Using full namespace name. For example, `:serene.core/xyz`
// To use this keyword you don't need the namespace `serene.core`
// to be loaded. It's just a name after all.
//
// 2. Using aliased namespaces. For example `::xyz` or `::core/xyz`.
// Using two colons instructs Serene to use aliased namespaces
// with the keyword. In the `::xyz` since the ns part is missing
// Serene will use the current namespace. For instance:
//
// ```
// user> ::xyz
// :user/xyz
// ```
// As you can see `::xyz` and `:user/xyz` (`user` being the ns name)
// are literally the same.
//
// But if we provide the ns part (`::core/xyz` example), a namespace
// with that alias has to be loaded and present in the current
// namespace. For example:
//
// ```
// user> (require '(examples.hello-world hello))
// <ns: examples.hello-world at /home/lxsameer/src/serene/serene/bootstrap/examples/hello-world.srn>
// user> ::hello/xyz
// :examples.hello-world/xyz
// ```
// As you can see we had to load the ns with the `hello` alias to be
// able to use the alias in a keyword.
//
// TODO: Cache the keywords in the runtime on the first eval so we
// done have to evaluate them over and over again. It can be achieved
// by caching the `hash` value in the keyword itself and maintain a
// hashmap in the runtime from hash codes to a pointer to the keyword.
// But garbage collecting it would be an issue since Golang doesn't support
// weak pointer, but since bootstrap version of Serene is used only to
// bootstrap the compiler it's ok to ignore that for now
import (
"fmt"
"strings"
"serene-lang.org/bootstrap/pkg/ast"
"serene-lang.org/bootstrap/pkg/hash"
)
type Keyword struct {
Node
ExecutionScope
name string
// nsName is the string that is used as the namespace name. It
// might be an ns alias in the current ns or the full namespace
// as well. The first time that this keyword gets evaluated the
// `ns` field will be populated by a pointer to the actual
// namespace which is referrenced to via `nsName` and after that
// nsName will be pretty much useless.
nsName string
// It will be populated after the first evaluation of this keyword
ns *Namespace
// Is it like :serene.core/something
nsQualified bool
// Is it like ::s/something ?
aliased bool
}
func (k *Keyword) GetType() ast.NodeType {
return ast.Keyword
}
func (k *Keyword) String() string {
if k.nsQualified {
if k.ns == nil {
return ":" + k.nsName + "/" + k.name
}
return ":" + k.ns.GetName() + "/" + k.name
}
return ":" + k.name
}
func (k *Keyword) ToDebugStr() string {
var ns string
if k.nsQualified {
ns = k.ns.GetName() + "/"
} else {
ns = ""
}
return fmt.Sprintf("<keword :%s%s at %p>", ns, k.name, k)
}
func (k *Keyword) Hash() uint32 {
bytes := []byte(k.name)
nameHash := hash.Of(append([]byte{byte(ast.Keyword)}, bytes...))
if k.nsQualified {
if k.ns != nil {
return hash.CombineHashes(hash.Of([]byte(k.ns.GetName())), nameHash)
}
}
return nameHash
}
func (k *Keyword) SetNS(ns *Namespace) {
k.ns = ns
}
func (k *Keyword) IsNSQualified() bool {
return k.nsQualified
}
// Eval initializes the keyword by looking up the possible
// alias name and set it in the keyword.
func (k *Keyword) Eval(rt *Runtime, scope IScope) (*Keyword, IError) {
if k.nsQualified && k.aliased {
aliasedNS := rt.CurrentNS()
if k.nsName != "" {
aliasedNS = rt.CurrentNS().LookupExternal(k.nsName)
}
if aliasedNS == nil {
return nil, MakeError(rt, k, fmt.Sprintf("can't find the alias '%s' in the current namespace.", k.nsName))
}
k.ns = aliasedNS
return k, nil
}
return k, nil
}
// Extracts the different parts of the keyword
func extractParts(s string) (nspart, namepart string) {
parts := strings.Split(s, "/")
namepart = parts[0]
if len(parts) == 2 {
nspart = parts[0]
namepart = parts[1]
}
return
}
func MakeKeyword(n Node, name string) (*Keyword, IError) {
if strings.Count(name, ":") > 2 {
return nil, MakeSyntaxErrorf(n, "can't parse the keyword with more that two colons: '%s'", name)
}
if strings.Count(name, "/") > 1 {
return nil, MakeSyntaxErrorf(n, "illegal namespace path for the given keyword: '%s'", name)
}
var nsName string
var kwName string
keyword := name
nsQualified := false
aliased := false
if strings.HasPrefix(name, "::") {
nsQualified = true
aliased = true
keyword = name[2:]
} else if strings.HasPrefix(name, ":") && strings.Count(name, "/") == 1 {
nsQualified = true
keyword = name[1:]
} else if strings.HasPrefix(name, ":") {
keyword = name[1:]
}
nsName, kwName = extractParts(keyword)
return &Keyword{
Node: n,
name: kwName,
nsName: nsName,
nsQualified: nsQualified,
aliased: aliased,
}, nil
}

View File

@ -1,152 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
import (
"fmt"
"strings"
"serene-lang.org/bootstrap/pkg/ast"
"serene-lang.org/bootstrap/pkg/hash"
)
/** WARNING:
This List implementation may look simple and performant but since
we're using a slice here. But in fact it's not memory efficient at
all. We need to rewrite this later to be a immutable and persistent
link list of cons.
*/
type List struct {
Node
ExecutionScope
exprs []IExpr
}
// Implementing IExpr for List ---
func (l *List) GetType() ast.NodeType {
return ast.List
}
func (l *List) String() string {
var strs []string
for _, e := range l.exprs {
strs = append(strs, e.String())
}
return fmt.Sprintf("(%s)", strings.Join(strs, " "))
}
func (l *List) ToDebugStr() string {
return fmt.Sprintf("%#v", l)
}
// END: IExpr ---
// Implementing ISeq for List ---
func (l *List) First() IExpr {
if l.Count() == 0 {
return MakeNil(MakeNodeFromExpr(l))
}
return l.exprs[0]
}
func (l *List) Rest() ISeq {
if l.Count() < 2 {
return MakeEmptyList(l.Node)
}
rest := l.exprs[1:]
node := l.Node
if len(rest) > 0 {
// n won't be nil here but we should check anyway
n := MakeNodeFromExprs(rest)
if n == nil {
panic("'MakeNodeFromExprs' has returned nil for none empty array of exprs")
}
node = *n
}
return MakeList(node, rest)
}
func (l *List) Hash() uint32 {
bytes := []byte("TODO")
return hash.Of(append([]byte{byte(ast.List)}, bytes...))
}
// END: ISeq ---
// Implementing ICountable for List ---
func (l *List) Count() int {
return len(l.exprs)
}
// END: ICountable ---
// Implementing IColl for List ---
func (l *List) ToSlice() []IExpr {
return l.exprs
}
func (l *List) Cons(e IExpr) IExpr {
elements := append([]IExpr{e}, l.ToSlice()...)
node := MakeNodeFromExprs(elements)
// Since 'elements' is not empty node won't be nil but we should
// check anyway
if node == nil {
node = &l.Node
}
return MakeList(*node, elements)
}
// END: IColl ---
func (l *List) AppendToList(e IExpr) *List {
l.exprs = append(l.exprs, e)
return l
}
func ListStartsWith(l *List, sym string) bool {
if l.Count() > 0 {
firstElem := l.First()
if firstElem.GetType() == ast.Symbol {
return firstElem.(*Symbol).GetName() == sym
}
}
return false
}
func MakeList(n Node, elements []IExpr) *List {
return &List{
Node: n,
exprs: elements,
}
}
func MakeEmptyList(n Node) *List {
return &List{
Node: n,
exprs: []IExpr{},
}
}

View File

@ -1,106 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
// TODO:
// * Add support for `before` and `after` state in macroexpantion
// and call stack. So in case of an error. Users should be able
// to see the forms before and after expansion.
import (
"serene-lang.org/bootstrap/pkg/ast"
)
// Serene macros are in fact functions with the `isMacro` flag set to true.
// We have only normal macro implementation in bootstrap version of serene in
// compare to reader macros and evaluator macros and and other types.
// MakeMacro creates a macro with the given `params` and `body` in
// the given `scope`.
func MakeMacro(scope IScope, name string, params IColl, body *Block) *Function {
return &Function{
name: name,
scope: scope,
params: params,
body: body,
isMacro: true,
}
}
// isMacroCall looks up the given `form` in the given `scope` if it is a symbol.
// If there is a value associated with the symbol in the scope, it will be checked
// to be a macro.
func isMacroCall(rt *Runtime, scope IScope, form IExpr) (*Function, bool) { //nolint:interfacer
if form.GetType() == ast.List {
list := form.(*List)
if list.Count() == 0 {
return nil, false
}
first := list.First()
var macro IExpr = nil
if first.GetType() == ast.Symbol {
binding := scope.Lookup(rt, first.(*Symbol).GetName())
if binding != nil && binding.Public {
macro = binding.Value
}
}
if macro != nil {
if macro.GetType() == ast.Fn && macro.(*Function).IsMacro() {
return macro.(*Function), true
}
}
}
return nil, false
}
// applyMacro works very similar to how we evaluate function calls the only difference
// is that we don't evaluate the arguments and create the bindings in the scope of the
// body directly as they are. It's Lisp Macroes after all.
func applyMacro(rt *Runtime, macro *Function, args IColl) (IExpr, IError) {
mscope, e := MakeFnScope(rt, macro.GetScope(), macro.GetParams(), args)
if e != nil {
return nil, e
}
return EvalForms(rt, mscope, macro.GetBody())
}
// macroexpand expands the given `form` as a macro and returns the resulted
// expression
func macroexpand(rt *Runtime, scope IScope, form IExpr) (IExpr, IError) {
var macro *Function
var e IError
ok := false
for {
macro, ok = isMacroCall(rt, scope, form)
if !ok {
return form, nil
}
form, e = applyMacro(rt, macro, form.(IColl).Rest().(*List))
if e != nil {
return nil, e
}
}
}

View File

@ -1,264 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
import (
"fmt"
"serene-lang.org/bootstrap/pkg/ast"
"serene-lang.org/bootstrap/pkg/hash"
)
type INamespace interface {
// TODO: Add a method to fetch the source code based on the source value
DefineGlobal()
LookupGlobal()
GetRootScope() IScope
// return the fully qualified name of the namespace
GetName() string
getForms() *Block
setForms(forms *Block)
}
type Namespace struct {
// Fully qualified name of the ns. e.g `serene.core`
name string
// The root scope of the namespace which keeps the global definitions
// and values of the scope. But not the external namespaces and values
rootScope Scope
// TODO: Add a method to fetch the source code based on this value
// Path to the source of the name space, it can be a file path
// or anything related to the ns loader (not implemented yet).
source string
externals map[string]*Namespace
forms Block
}
func (n *Namespace) GetType() ast.NodeType {
return ast.Namespace
}
func (n *Namespace) GetLocation() *ast.Location {
return ast.MakeUnknownLocation()
}
func (n *Namespace) String() string {
return fmt.Sprintf("<ns: %s at %s>", n.name, n.source)
}
func (n *Namespace) ToDebugStr() string {
return fmt.Sprintf("<ns: %s at %s>", n.name, n.source)
}
func (n *Namespace) GetExecutionScope() IScope {
return nil
}
func (n *Namespace) SetExecutionScope(scope IScope) {}
// DefineGlobal inserts the given expr `v` to the root scope of
// `n`. The `public` parameter determines whether the public
// value is accessible publicly or not (in other namespaces).
func (n *Namespace) DefineGlobal(k string, v IExpr, public bool) {
n.rootScope.Insert(k, v, public)
}
// LookupGlobal looks up the value represented by the ns qualified
// symbol `sym` in the external symbols table. Simply looking up
// a public value from an external namespace.
func (n *Namespace) LookupGlobal(rt *Runtime, sym *Symbol) *Binding {
// TODO: Find a better name for this method, `LookupExternal` maybe
if !sym.IsNSQualified() {
return nil
}
externalNS, ok := n.externals[sym.GetNSPart()]
if !ok {
return nil
}
externalScope := externalNS.GetRootScope()
return externalScope.Lookup(rt, sym.GetName())
}
func (n *Namespace) GetRootScope() IScope {
return &n.rootScope
}
func (n *Namespace) GetName() string {
return n.name
}
func (n *Namespace) Hash() uint32 {
return hash.Of([]byte(n.String()))
}
func (n *Namespace) hasExternal(nsName string) bool {
_, ok := n.externals[nsName]
return ok
}
// LookupExternal looks up the given `alias` in the `externals` table
// of the namespace.
func (n *Namespace) LookupExternal(alias string) *Namespace {
if n.hasExternal(alias) {
return n.externals[alias]
}
return nil
}
func (n *Namespace) setExternal(name string, ns *Namespace) {
n.externals[name] = ns
}
func (n *Namespace) setForms(block *Block) {
n.forms = *block
}
func (n *Namespace) getForms() *Block {
return &n.forms
}
// requireNS finds and loads the namespace addressed by the given
// `ns` string.
func requireNS(rt *Runtime, ns *Symbol) (*Namespace, IError) {
// TODO: use a hashing algorithm to avoid reloading an unchanged namespace
loadedForms, err := rt.loadNS(ns)
if err != nil {
return nil, err
}
body := loadedForms.forms
source := loadedForms.source
if body.Count() == 0 {
return nil, MakeError(
rt,
body,
fmt.Sprintf("The '%s' ns source code doesn't start with an 'ns' form.", ns),
)
}
namespace := MakeNS(rt, ns.GetName(), source)
namespace.setForms(body)
return &namespace, nil
}
// RequireNamespace finds and loads the naemspace which is addressed by the
// given expression `namespace` and add the loaded namespace to the list
// of available namespaces on the runtime and add the correct reference
// to the current namespace. If `namespace` is a symbol, then the name
// of the symbol would be used as the ns name and an alias with the
// same name will be added to the current namespace as the external
// reference. If it is a IColl (List at the moment), then the symbol
// in the first element would be the ns name and the second symbol
// will be the name of the alias to be used.
func RequireNamespace(rt *Runtime, namespace IExpr) (IExpr, IError) {
var alias string
var ns *Symbol
switch namespace.GetType() {
case ast.Symbol:
ns = namespace.(*Symbol)
alias = ns.GetName()
case ast.List:
list := namespace.(*List)
first := list.First()
if first.GetType() != ast.Symbol {
return nil, MakeError(rt, first, "The first element has to be a symbol")
}
second := list.Rest().First()
if second.GetType() != ast.Symbol {
return nil, MakeError(rt, first, "The second element has to be a symbol")
}
ns = first.(*Symbol)
alias = second.(*Symbol).GetName()
default:
return nil, MakeError(rt, ns, "Don't know how to load the given namespace")
}
loadedNS, err := requireNS(rt, ns)
if err != nil {
return nil, err
}
// Since we want to change the current ns to the loaded ns while evaluating it.
prevNS := rt.CurrentNS()
rt.InsertNS(ns.GetName(), loadedNS)
inserted := rt.setCurrentNS(loadedNS.GetName())
if !inserted {
return nil, MakeError(
rt,
loadedNS,
fmt.Sprintf(
"the namespace '%s' didn't get inserted in the runtime.",
loadedNS.GetName()),
)
}
// Evaluating the body of the loaded ns (Check for ns validation happens here)
loadedNS, e := EvalNSBody(rt, loadedNS)
// Set the current ns back first and then check for an error
inserted = rt.setCurrentNS(prevNS.GetName())
if !inserted {
return nil, MakeError(
rt,
loadedNS,
fmt.Sprintf(
"can't set the current ns back to '%s' from '%s'.",
prevNS.GetName(),
loadedNS.GetName()),
)
}
if e != nil {
return nil, e
}
// Set the external reference to the loaded ns in the current ns
prevNS.setExternal(alias, loadedNS)
return loadedNS, nil
}
// MakeNS creates a new namespace with the given `name` and `source`
func MakeNS(rt *Runtime, name, source string) Namespace {
s := MakeScope(rt, nil, &name)
return Namespace{
name: name,
rootScope: *s,
source: source,
externals: map[string]*Namespace{},
}
}

View File

@ -1,46 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
import "serene-lang.org/bootstrap/pkg/ast"
type Nil struct {
Node
ExecutionScope
}
func (n *Nil) GetType() ast.NodeType {
return ast.Nil
}
func (n *Nil) String() string {
return NILFORM
}
func (n *Nil) ToDebugStr() string {
return NILFORM
}
func (n *Nil) Hash() uint32 {
return 0
}
func MakeNil(n Node) *Nil {
return &Nil{Node: n}
}

View File

@ -1,55 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
import (
"serene-lang.org/bootstrap/pkg/ast"
"serene-lang.org/bootstrap/pkg/hash"
)
type NothingType struct{}
var Nothing = NothingType{}
func (n NothingType) GetType() ast.NodeType {
return ast.Nothing
}
func (n NothingType) Hash() uint32 {
bytes := []byte("Nothing")
return hash.Of(append([]byte{byte(ast.Block)}, bytes...))
}
func (n NothingType) GetLocation() *ast.Location {
return ast.MakeUnknownLocation()
}
func (n NothingType) String() string {
return ""
}
func (n NothingType) ToDebugStr() string {
return ""
}
func (n NothingType) GetExecutionScope() IScope {
return nil
}
func (n NothingType) SetExecutionScope(scope IScope) {}

View File

@ -1,204 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
import (
"encoding/binary"
"fmt"
"math"
"strconv"
"serene-lang.org/bootstrap/pkg/ast"
"serene-lang.org/bootstrap/pkg/hash"
)
type INumber interface {
IExpr
// Int() int
// I8() int8
// I16() int16
// I32() int32
I64() int64
// UInt() uint
// UI8() uint8
// UI16() uint16
// UI32() uint32
// UI64() uint64
// F32() float32
F64() float64
// Add(n Number) Number
// TDOD: Add basic operators here
}
/** WARNING:
These are really stupid implementations of numbers we
need better implmentations later, but it's ok for something
to begin with
*/
type Integer struct {
Node
// ExecutionScope checkout IScopable
scope IScope
ExecutionScope
value int64
}
func (i *Integer) GetType() ast.NodeType {
return ast.Number
}
func (i *Integer) Hash() uint32 {
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, uint64(i.value))
return hash.Of(b)
}
func (i *Integer) GetExecutionScope() IScope {
return i.scope
}
func (i *Integer) SetExecutionScope(scope IScope) {
i.scope = scope
}
func (i *Integer) String() string {
return fmt.Sprintf("%d", i.value)
}
func (i *Integer) ToDebugStr() string {
return fmt.Sprintf("%#v", i)
}
func (i *Integer) I64() int64 {
return i.value
}
func (i *Integer) F64() float64 {
return float64(i.value)
}
func MakeInteger(x interface{}) (*Integer, IError) {
var value int64
switch x := x.(type) {
case uint32:
value = int64(x)
case int32:
value = int64(x)
default:
return nil, MakePlainError(fmt.Sprintf("don't know how to make 'integer' out of '%s'", x))
}
return &Integer{
value: value,
}, nil
}
type Double struct {
Node
// ExecutionScope checkout IScopable
scope IScope
value float64
}
func (d *Double) GetType() ast.NodeType {
return ast.Number
}
func (d *Double) Hash() uint32 {
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, math.Float64bits(d.value))
return hash.Of(b)
}
func (d *Double) String() string {
return fmt.Sprintf("%f", d.value)
}
func (d *Double) ToDebugStr() string {
return fmt.Sprintf("%#v", d)
}
func (d *Double) GetExecutionScope() IScope {
return d.scope
}
func (d *Double) SetExecutionScope(scope IScope) {
d.scope = scope
}
func (d *Double) I64() int64 {
return int64(d.value)
}
func (d *Double) F64() float64 {
return d.value
}
func MakeNumberFromStr(n Node, strValue string, isDouble bool) (INumber, error) {
var ret INumber
if isDouble {
v, err := strconv.ParseFloat(strValue, 64)
if err != nil {
return nil, err
}
ret = &Double{
Node: n,
value: v,
}
} else {
v, err := strconv.ParseInt(strValue, 10, 64)
if err != nil {
return nil, err
}
ret = &Integer{
Node: n,
value: v,
}
}
return ret, nil
}
func MakeDouble(x interface{}) (*Double, IError) {
var value float64
switch x := x.(type) {
case uint32:
value = float64(x)
case int32:
value = float64(x)
case float32:
value = float64(x)
default:
return nil, MakePlainError(fmt.Sprintf("don't know how to make 'double' out of '%s'", x))
}
return &Double{
value: value,
}, nil
}

View File

@ -1,589 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
// Parser Implementation:
// * `ParseToAST` is the entry point of the parser
// * It's a manual parser with look ahead factor of (1)
// * It parsers the input string to a tree of `IEpxr`s
//
// TODOs:
// * Add a shortcut for anonymous functions similar to `#(...)` clojure
// syntax
// * Add the support for strings
// * Add the support for kewords
// * Add a shortcut for the `deref` function like `@x` => `(deref x)`
// * A line of comment at the end of a list definition causes a synxtax error.
// We need to fix it. For example:
// (asdb xyz
// ;; problematic comment line
// )
// Will fails. The reason being we call `readExpr` in `readList` and in the
// `readExpr` when we read a line of comment we jump to a label and try to
// read another expr which in our case it would read the end of list and throw
// and error
import (
"strings"
"unicode"
"serene-lang.org/bootstrap/pkg/ast"
)
// An array of the valid characters that be be used in a symbol
var validChars = []rune{'!', '$', '%', '&', '*', '+', '-', '.', '~', '/', ':', '<', '=', '>', '?', '@', '^', '_'}
// IParsable defines the common interface which any parser has to implement.
type IParsable interface {
// Reads the next character in the buffer with respect to skipWhitespace
// parameter which basically jumps over whitespace and some conceptual
// equivalent of a whitespace like '\n'
next(skipWhitespace bool) *string
// Similar to the `next` but it won't change the position in the buffer
// so an imidiate `next` function after a `peek` will read the same char
// but will move the position, and a series of `peek` calls will read the
// same function over and over again without changing the position in the
// buffer.
peek(skipWhitespace bool) *string
// Moves back the position by one in the buffer.
back()
// Returns the current position in the buffer
GetLocation() int
GetSource() *ast.Source
Buffer() *[]string
}
// StringParser is an implementation of the IParsable that operates on strings.
// To put it simply it parses input strings
type StringParser struct {
buffer []string
pos int
source string
// This slice holds the boundaries of lines in the buffer. Basically
// each element determines the position which a line ends and the line
// number directly maps to the position of it's boundary in the slice.
lineIndex []int
}
// Implementing IParsable for StringParser ---
// updateLineIndex reads the current character and if it is an end of line, then
// it will update the line index to add the boundaries of the current line.
func (sp *StringParser) updateLineIndex(pos int) {
if pos < len(sp.buffer) {
c := sp.buffer[pos]
if c == "\n" {
if len(sp.lineIndex) > 0 {
if sp.lineIndex[len(sp.lineIndex)-1] != pos+1 {
// Including the \n itself
sp.lineIndex = append(sp.lineIndex, pos+1)
}
} else {
sp.lineIndex = append(sp.lineIndex, pos+1)
}
}
}
}
// Returns the next character in the buffer
func (sp *StringParser) next(skipWhitespace bool) *string {
if sp.pos >= len(sp.buffer) {
return nil
}
char := sp.buffer[sp.pos]
sp.updateLineIndex(sp.pos)
sp.pos++
if skipWhitespace && isSeparator(&char) {
return sp.next(skipWhitespace)
}
return &char
}
// isSeparator returns a boolean indicating whether the given character `c`
// contains a separator or not. In a Lisp whitespace and someother characters
// are conceptually the same and we need to treat them the same as well.
func isSeparator(c *string) bool {
if c == nil {
return false
}
r := []rune(*c)[0]
if r == ' ' || r == '\t' || r == '\n' || r == '\f' {
return true
}
return false
}
// Return the character of the buffer without consuming it
func (sp *StringParser) peek(skipWhitespace bool) *string {
if sp.pos >= len(sp.buffer) {
return nil
}
c := sp.buffer[sp.pos]
if isSeparator(&c) && skipWhitespace {
sp.updateLineIndex(sp.pos)
sp.pos++
return sp.peek(skipWhitespace)
}
return &c
}
// Move the char pointer back by one character
func (sp *StringParser) back() {
if sp.pos > 0 {
sp.pos--
}
}
func (sp *StringParser) GetLocation() int {
return sp.pos
}
func (sp *StringParser) GetSource() *ast.Source {
return &ast.Source{
Buffer: &sp.buffer,
NS: sp.source,
LineIndex: &sp.lineIndex,
}
}
func (sp *StringParser) Buffer() *[]string {
return &sp.buffer
}
// END: IParsable ---
// makeErrorAtPoint is a helper function which generates an `IError` that
// points at the current position of the buffer.
func makeErrorAtPoint(p IParsable, msg string, a ...interface{}) IError {
n := MakeSinglePointNode(p.GetSource(), p.GetLocation())
return MakeSyntaxErrorf(n, msg, a...)
}
// makeErrorFromError is a function which wraps a Golang error in an IError
func makeErrorFromError(parser IParsable, e error) IError {
//nolint:govet
return makeErrorAtPoint(parser, "%w", e)
}
func contains(s []rune, c rune) bool {
for _, v := range s {
if v == c {
return true
}
}
return false
}
func isValidForSymbol(char string) bool {
c := rune(char[0])
return contains(validChars, c) || unicode.IsLetter(c) || unicode.IsDigit(c)
}
func readKeyword(parser IParsable) (IExpr, IError) {
symbol, err := readRawSymbol(parser)
if err != nil {
return nil, err
}
node := MakeNodeFromExpr(symbol)
return MakeKeyword(node, ":"+symbol.(*Symbol).String())
}
// readRawSymbol reads a symbol from the current position forward
func readRawSymbol(parser IParsable) (IExpr, IError) {
c := parser.peek(false)
var symbol string
if c == nil {
return nil, makeErrorAtPoint(parser, "unexpected enf of file while parsing a symbol")
}
// Does the symbol starts with a valid character or not
if isValidForSymbol(*c) {
parser.next(false)
symbol = *c
} else {
return nil, makeErrorAtPoint(parser,
"unexpected character: got '%s', expected a symbol at %d",
*c,
parser.GetLocation(),
)
}
// read the rest of the symbol
for {
c := parser.next(false)
if c == nil {
break
}
if isValidForSymbol(*c) {
symbol += *c
} else {
parser.back()
break
}
}
node := MakeNode(parser.GetSource(), parser.GetLocation()-len(symbol), parser.GetLocation())
sym, err := MakeSymbol(node, symbol)
if err != nil {
err.SetNode(&node)
return nil, err
}
return sym, nil
}
func readString(parser IParsable) (IExpr, IError) {
str := ""
for {
c := parser.next(false)
if c == nil {
return nil, makeErrorAtPoint(parser, "reached end of file while scanning a string")
}
if *c == "\"" {
node := MakeNode(parser.GetSource(), parser.GetLocation()-len(str), parser.GetLocation())
return MakeString(node, str), nil
}
if *c == "\\" {
c = parser.next(false)
switch *c {
case "n":
str += "\n"
case "t":
str += "\t"
case "r":
str += "\r"
case "\\":
str += "\\"
case "\"":
str += "\""
default:
return nil, makeErrorAtPoint(parser, "Unsupported escape character: \\%s", *c)
}
} else {
str += *c
}
}
}
// readNumber reads a number with respect to its sign and whether it's, a ...interface{}
// a decimal or a float
func readNumber(parser IParsable, neg bool) (IExpr, IError) {
isDouble := false
result := ""
if neg {
result = "-"
}
for {
c := parser.next(false)
if c == nil {
break
}
if *c == "." && isDouble {
return nil, makeErrorAtPoint(parser, "a double with more that one '.' ???")
}
if *c == "." {
isDouble = true
result += *c
continue
}
// Weird, But go won't stop complaining without this swap
char := *c
r := rune(char[0])
if unicode.IsDigit(r) {
result += *c
} else if isValidForSymbol(char) {
return nil, makeErrorAtPoint(parser, "Illegal token while scanning for a number.")
} else {
parser.back()
break
}
}
n := MakeSinglePointNode(parser.GetSource(), parser.GetLocation())
n.location.DecStart(len(result))
value, err := MakeNumberFromStr(n, result, isDouble)
if err != nil {
return nil, makeErrorFromError(parser, err)
}
return value, nil
}
// readSymbol reads a symbol and return the appropriate type of expression
// based on the symbol conditions. For example it will read a number if the
// symbol starts with a number or a neg sign or a string if it starts with '\"'
// and a raw symbol otherwise
func readSymbol(parser IParsable) (IExpr, IError) {
c := parser.peek(false)
if c == nil {
return nil, makeErrorAtPoint(parser, "unexpected end of file while scanning a symbol")
}
if *c == "\"" {
parser.next(false)
return readString(parser)
}
// Weird, But go won't stop complaining without this swap
char := *c
r := rune(char[0])
if unicode.IsDigit(r) {
return readNumber(parser, false)
}
if *c == "-" {
parser.next(true)
c := parser.peek(false)
// Weird, But go won't stop complaining without this swap
char := *c
r := rune(char[0])
if unicode.IsDigit(r) {
return readNumber(parser, true)
}
// Unread '-'
parser.back()
return readRawSymbol(parser)
}
return readRawSymbol(parser)
}
// readList reads a List recursively.
func readList(parser IParsable) (IExpr, IError) {
list := []IExpr{}
for {
c := parser.peek(true)
if c == nil {
return nil, makeErrorAtPoint(parser, "reaching the end of file while reading a list")
}
if *c == ")" {
parser.next(true)
break
} else {
val, err := readExpr(parser)
if err != nil {
return nil, err
}
list = append(list, val)
}
}
node := MakeNodeFromExprs(list)
if node == nil {
n := MakeSinglePointNode(parser.GetSource(), parser.GetLocation())
node = &n
}
node.location.DecStart(1)
node.location.IncEnd(1)
return MakeList(*node, list), nil
}
//nolint:unparam
func readComment(parser IParsable) (IExpr, IError) {
for {
c := parser.next(false)
if c == nil || *c == "\n" {
return nil, nil
}
}
}
// readQuotedExpr reads the backquote and replace it with a call
// to the `quasiquote` macro.
func readQuotedExpr(parser IParsable, quote string) (IExpr, IError) {
expr, err := readExpr(parser)
if err != nil {
return nil, err
}
node := MakeNode(parser.GetSource(), parser.GetLocation(), parser.GetLocation())
sym, err := MakeSymbol(node, quote)
if err != nil {
err.SetNode(&node)
return nil, err
}
listElems := []IExpr{sym, expr}
listNode := MakeNodeFromExprs(listElems)
// listNode won't be nil in this case but it doesn't
// mean we shouldn't check
if listNode == nil {
n := MakeSinglePointNode(parser.GetSource(), parser.GetLocation())
listNode = &n
}
listNode.location.DecStart(1)
listNode.location.IncStart(1)
return MakeList(*listNode, listElems), nil
}
// readUnquotedExpr reads different unquoting expressions from their short representaions.
// ~a => (unquote a)
// ~@a => (unquote-splicing a)
// Note: `unquote` and `unquote-splicing` are not global functions or special, they are bounded
// to quasiquoted expressions only.
func readUnquotedExpr(parser IParsable) (IExpr, IError) {
c := parser.peek(true)
if c == nil {
return nil, makeErrorAtPoint(parser, "end of file while reading an unquoted expression")
}
var sym IExpr
var err IError
var expr IExpr
node := MakeNode(parser.GetSource(), parser.GetLocation(), parser.GetLocation())
if *c == "@" {
parser.next(true)
sym, err = MakeSymbol(node, "unquote-splicing")
if err != nil {
err.SetNode(&node)
} else {
expr, err = readExpr(parser)
}
} else {
sym, err = MakeSymbol(node, "unquote")
if err != nil {
err.SetNode(&node)
} else {
expr, err = readExpr(parser)
}
}
if err != nil {
return nil, err
}
listElems := []IExpr{sym, expr}
listNode := MakeNodeFromExprs(listElems)
// listNode won't be nil in this case but it doesn't
// mean we shouldn't check
if listNode == nil {
n := MakeSinglePointNode(parser.GetSource(), parser.GetLocation())
listNode = &n
}
listNode.location.DecStart(1)
listNode.location.IncStart(1)
return MakeList(*listNode, listElems), nil
}
// readExpr reads one expression from the input. This function is the most
// important function in the parser which dispatches the call to different
// reader functions based on the first character
func readExpr(parser IParsable) (IExpr, IError) {
loop:
c := parser.next(true)
if c == nil {
// We're done reading
return nil, nil
}
if *c == "'" {
return readQuotedExpr(parser, "quote")
}
if *c == "~" {
return readUnquotedExpr(parser)
}
if *c == "`" {
return readQuotedExpr(parser, "quasiquote")
}
if *c == "(" {
return readList(parser)
}
if *c == ";" {
readComment(parser)
goto loop
}
if *c == ":" {
return readKeyword(parser)
}
parser.back()
return readSymbol(parser)
}
// ParseToAST is the entry function to the reader/parser which
// converts the `input` string to a `Block` of code. A block
// by itself is not something available to the language. It's
// just anbstraction for a ordered collection of expressions.
// It doesn't have anything to do with the concept of blocks
// from other programming languages.
func ParseToAST(ns, input string) (*Block, IError) {
var forms Block
parser := StringParser{
buffer: strings.Split(input, ""),
pos: 0,
source: ns,
}
for {
expr, err := readExpr(&parser)
if err != nil {
return nil, err
}
if expr == nil {
break
}
forms.Append(expr)
}
return &forms, nil
}

View File

@ -1,195 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
import (
"fmt"
"strings"
"github.com/gookit/color"
"serene-lang.org/bootstrap/pkg/ast"
"serene-lang.org/bootstrap/pkg/errors"
)
func toRepresanbleString(forms ...IRepresentable) string {
var results []string
for _, x := range forms {
results = append(results, x.String())
}
return strings.Join(results, " ")
}
func toPrintableString(forms ...IRepresentable) string {
var results []string
for _, x := range forms {
if printable, ok := x.(IPrintable); ok {
results = append(results, printable.PrintToString())
continue
}
results = append(results, x.String())
}
return strings.Join(results, " ")
}
func Pr(rt *Runtime, forms ...IRepresentable) {
fmt.Print(toRepresanbleString(forms...))
}
func Prn(rt *Runtime, forms ...IRepresentable) {
fmt.Println(toRepresanbleString(forms...))
}
func Print(rt *Runtime, forms ...IRepresentable) {
fmt.Print(toPrintableString(forms...))
}
func Println(rt *Runtime, forms ...IRepresentable) {
fmt.Println(toPrintableString(forms...))
}
func printError(_ *Runtime, err IError, stage int) {
loc := err.GetLocation()
source := loc.GetSource()
startline := source.LineNumberFor(loc.GetStart())
if startline > 0 {
startline--
}
endline := source.LineNumberFor(loc.GetEnd()) + 1
var lines string
for i := startline; i <= endline; i++ {
line := source.GetLine(i)
if line != "----" {
lines += fmt.Sprintf("%d:\t%s\n", i, line)
}
}
color.Yellow.Printf(
"%d: At '%s':%d\n",
stage,
source.NS,
source.LineNumberFor(loc.GetStart()),
)
color.White.Printf("%s\n", lines)
errTag := color.Red.Sprint(err.GetErrType().String())
fmt.Printf("%s: %s\nAt: %d to %d\n", errTag, err.String(), loc.GetStart(), loc.GetEnd())
}
func frameCaption(traces *TraceBack, frameIndex int) string {
if frameIndex >= len(*traces) || frameIndex < 0 {
panic("Out of range index for the traceback array. It shouldn't happen!!!")
}
var prevFrame *Frame
place := "*run*"
frame := (*traces)[frameIndex]
loc := frame.Caller.GetLocation()
source := loc.GetSource()
if frameIndex != 0 {
prevFrame = (*traces)[frameIndex-1]
place = prevFrame.Callee.GetName()
}
return color.Yellow.Sprintf(
"%d: In function '%s' at '%s':%d\n",
frameIndex,
place,
source.NS,
source.LineNumberFor(loc.GetStart()),
)
}
func frameSource(traces *TraceBack, frameIndex int) string {
if frameIndex >= len(*traces) || frameIndex < 0 {
panic("Out of range index for the traceback array. It shouldn't happen!!!")
}
frame := (*traces)[frameIndex]
caller := frame.Caller
callerLoc := caller.GetLocation()
callerSource := callerLoc.GetSource()
startline := callerSource.LineNumberFor(callerLoc.GetStart())
if startline > 0 {
startline--
}
endline := callerSource.LineNumberFor(callerLoc.GetEnd()) + 1
var lines string
for i := startline; i <= endline; i++ {
fLoc := frame.Caller.GetLocation()
if fLoc.IsKnownLocaiton() {
line := fLoc.GetSource().GetLine(i)
if line != ast.OutOfRangeLine {
lines += fmt.Sprintf("%d:\t%s\n", i, line)
}
} else {
lines += "Builtin\n"
}
}
return lines
}
func printErrorWithTraceBack(_ *Runtime, err IError) {
trace := err.GetStackTrace()
for i := range *trace {
fmt.Print(frameCaption(trace, i))
color.White.Printf(frameSource(trace, i))
}
loc := err.GetLocation()
errTag := color.Red.Sprint(err.GetErrType().String())
fmt.Printf(
"%s: %s\nAt: %d to %d\n",
errTag,
err.String(),
loc.GetStart(),
loc.GetEnd(),
)
if err.GetErrno() != errors.E0000 {
fmt.Printf("For more information on this error try: `serene explain %s`\n", err.GetErrno())
}
}
func PrintError(rt *Runtime, err IError) {
switch err.GetErrType() {
case SyntaxError, SemanticError:
printError(rt, err, 0)
return
case RuntimeError:
printErrorWithTraceBack(rt, err)
return
default:
panic(fmt.Sprintf("Don't know about error type '%d'", err.GetErrType()))
}
}

View File

@ -1,173 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
// func qqLoop(xs []IExpr) IExpr {
// acc := MakeEmptyList()
// for i := len(xs) - 1; 0 <= i; i -= 1 {
// elem := xs[i]
// switch elem.GetType() {
// case ast.List:
// if ListStartsWith(elem.(*List), "unquote-splicing") {
// acc = MakeList([]IExpr{
// MakeSymbol(MakeNodeFromExpr(elem), "concat"),
// elem.(*List).Rest().First(),
// acc})
// continue
// }
// default:
// }
// acc = MakeList([]IExpr{
// MakeSymbol(MakeNodeFromExpr(elem), "cons"),
// quasiquote(elem),
// acc})
// }
// return acc
// }
// func quasiquote(e IExpr) IExpr {
// switch e.GetType() {
// case ast.Symbol:
// return MakeList([]IExpr{
// MakeSymbol(MakeNodeFromExpr(e), "quote"), e})
// case ast.List:
// list := e.(*List)
// if ListStartsWith(list, "unquote") {
// return list.Rest().First()
// }
// if ListStartsWith(list, "quasiquote") {
// return quasiquote(qqLoop(list.ToSlice()))
// }
// return qqLoop(list.ToSlice())
// default:
// return e
// }
// }
// const qqQUOTE string = "*quote*"
// func isSymbolEqual(e IExpr, name string) bool {
// if e.GetType() == ast.Symbol && e.(*Symbol).GetName() == name {
// return true
// }
// return false
// }
// func isQuasiQuote(e IExpr) bool {
// return isSymbolEqual(e, "quasiquote")
// }
// func isUnquote(e IExpr) bool {
// return isSymbolEqual(e, "unquote")
// }
// func isUnquoteSplicing(e IExpr) bool {
// return isSymbolEqual(e, "unquote-splicing")
// }
// func qqSimplify(e IExpr) (IExpr, IError) {
// return e, nil
// }
// func qqProcess(rt *Runtime, e IExpr) (IExpr, IError) {
// switch e.GetType() {
// // Example: `x => (*quote* x) => (quote x)
// case ast.Symbol:
// sym, err := MakeSymbol(MakeNodeFromExpr(e), qqQUOTE)
// if err != nil {
// //newErr := makeErrorAtPoint()
// // TODO: uncomment next line when we have stackable errors
// // newErr.stack(err)
// return nil, err
// }
// elems := []IExpr{
// sym,
// e,
// }
// n := MakeNodeFromExprs(elems)
// if n == nil {
// n = &sym.Node
// }
// return MakeList(
// *n,
// elems,
// ), nil
// case ast.List:
// list := e.(*List)
// first := list.First()
// // Example: ``... reads as (quasiquote (quasiquote ...)) and this if will check
// // for the second `quasiquote`
// if isQuasiQuote(first) {
// result, err := qqCompletelyProcess(rt, list.Rest().First())
// if err != nil {
// return nil, err
// }
// return qqProcess(rt, result)
// }
// // Example: `~x reads as (quasiquote (unquote x))
// if isUnquote(first) {
// return list.Rest().First(), nil
// }
// // ???
// if isUnquoteSplicing(first) {
// return nil, MakeError(rt, first, "'unquote-splicing' is not allowed out of a collection.")
// }
// // p := list
// // q := MakeEmptyList()
// // for {
// // p = p.Rest().(*List)
// // }
// }
// return e, nil
// }
// func qqRemoveQQFunctions(e IExpr) (IExpr, IError) {
// return e, nil
// }
// func qqCompletelyProcess(rt *Runtime, e IExpr) (IExpr, IError) {
// rawResult, err := qqProcess(rt, e)
// if err != nil {
// return nil, err
// }
// if rt.IsQQSimplificationEnabled() {
// rawResult, err = qqSimplify(rawResult)
// if err != nil {
// return nil, err
// }
// }
// return qqRemoveQQFunctions(rawResult)
// }
// func quasiquote(rt *Runtime, e IExpr) (IExpr, IError) {
// return qqCompletelyProcess(rt, e)
// }

View File

@ -1,23 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
func ReadString(ns, input string) (*Block, IError) {
return ParseToAST(ns, input)
}

View File

@ -1,217 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
import (
"fmt"
"io/ioutil"
"os"
"path"
"strings"
)
/** TODO:
Create an IRuntime interface to avoid using INamespace directly
*/
/** TODO:
Handle concurrency on the runtime level
*/
// loadedForms is used as "pair" implementation to keep the loaded
// expressions and the source where the expressions are coming from
type loadedForms struct {
source string
forms *Block
}
// TODO: Make the Runtime and it's fields thread safe
// Runtime is the most important data structure in Serene which hold
// the necessary information and the state of the interpreter at runtime (duh!).
// At any given time and thread only on Runtime has to exist and we always need
// to pass a pointer to the runtime around and avoid copying. (We don't have
// multithread support just yet but the Runtime must be thread safe).
type Runtime struct {
// A mapping from ns names (e.g some.ns.over.there) to the namespace
// data. This hashmap is owner of the namespaces, meaning that we only
// pass pointers to the namespaces around and any mutation has to happen
// here
namespaces map[string]Namespace
// A mapping from the builtin function names to the corresponding
// NativeFunction struct that implements them as expressions (IExpr).
// native functions are those which can be special form as well but
// they are more suited to be a function and at the same time we
// can't implement them in Serene itself.
builtins map[string]NativeFunction
// currentNS is the fully qualified name of the current namespace which
// is being processed (evaluates) at any given time. Since it's not
// thread safe at the moment we need to be careful changeing its value.
currentNS string
// paths is an array of filesystem paths that have we need to look into
// in order to find and load the namespaces. Similar to `load_path` in other
// languages
paths []string
Stack CallStack
// A to turn on the verbose mode, FOR DEVELOPMENT USE ONLY
debugMode bool
}
func (r *Runtime) IsDebugMode() bool {
return r.debugMode
}
func (r *Runtime) CurrentNS() *Namespace {
if r.currentNS == "" {
panic("current ns is not set on the runtime.")
}
ns, ok := r.namespaces[r.currentNS]
if !ok {
panic(fmt.Sprintf("namespace '%s' doesn't exist in the runtime.", r.currentNS))
}
return &ns
}
func (r *Runtime) setCurrentNS(nsName string) bool {
_, ok := r.namespaces[nsName]
if ok {
r.currentNS = nsName
return true
}
return false
}
// GetNS returns a pointer to the `Namespace` specified with the given name `ns`
// on the runtime.
func (r *Runtime) GetNS(ns string) (*Namespace, bool) {
namespace, ok := r.namespaces[ns]
return &namespace, ok
}
// CreateNS is a helper function to create a namespace and set it to be
// the current namespace of the runtime. `MakeNS` is much preferred
func (r *Runtime) CreateNS(name, source string, setAsCurrent bool) {
ns := MakeNS(r, name, source)
if setAsCurrent {
r.currentNS = name
}
r.namespaces[name] = ns
}
// IsQQSimplificationEnabled returns a boolean value indicating whether
// simplification of quasiquotation is enabled or not. If yes, we have
// to replace the quasiquote expanded forms with a simpler form to gain
// a better performance.
func (r *Runtime) IsQQSimplificationEnabled() bool {
// TODO: read the value of this flag from the arguments of serene
// and set the default to true
return false
}
// nsNameToPath converts a namespace name to the filesystem equivalent path
func nsNameToPath(ns string) string {
replacer := strings.NewReplacer(
".", "/",
// TODO: checkout the different OSs for character supports in
// the filesystem level
// "-", "_",
)
return replacer.Replace(ns) + ".srn"
}
// LoadNS looks up the namespace specified by the given name `ns`
// and reads the content as expressions (parse it) and returns the
// expressions.
func (r *Runtime) loadNS(ns *Symbol) (*loadedForms, IError) {
nsFile := nsNameToPath(ns.GetName())
for _, loadPath := range r.paths {
possibleFile := path.Join(loadPath, nsFile)
if r.debugMode {
fmt.Printf("[DEBUG] Looking for '%s' in '%s'", possibleFile, loadPath)
}
_, err := os.Stat(possibleFile)
if err != nil {
continue
}
data, err := ioutil.ReadFile(possibleFile)
if err != nil {
readError := MakeError(
r,
ns,
fmt.Sprintf("error while reading the file at %s", possibleFile),
)
readError.WithError(err)
return nil, readError
}
body, e := ReadString(ns.GetName(), string(data))
if e != nil {
return nil, e
}
return &loadedForms{possibleFile, body}, nil
}
// TODO: Add the load paths to the error message here
return nil, MakeError(r, ns, fmt.Sprintf("Can't find the namespace '%s' in any of load paths.", ns))
}
func (r *Runtime) InsertNS(nsName string, ns *Namespace) {
r.namespaces[nsName] = *ns
}
func (r *Runtime) LookupBuiltin(k string) IExpr {
builtinfn, ok := r.builtins[k]
if ok {
return &builtinfn
}
return nil
}
// MakeRuntime creates a Runtime and returns a pointer to it. Any
// runtime initialization such as adding default namespaces and vice
// versa has to happen here.
func MakeRuntime(paths []string, flags map[string]bool) *Runtime {
rt := Runtime{
namespaces: map[string]Namespace{},
currentNS: "",
debugMode: flags["debugMode"],
paths: paths,
Stack: MakeCallStack(flags["stackDebugMode"]),
}
rt.builtins = BUILTINS
return &rt
}

View File

@ -1,107 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
import "fmt"
type IScope interface {
Lookup(rt *Runtime, k string) *Binding
Insert(k string, v IExpr, public bool)
GetNS(rt *Runtime) *Namespace
SetNS(ns *string)
}
type Binding struct {
Value IExpr
Public bool
}
type Scope struct {
bindings map[string]Binding
parent *Scope
ns *string
}
func (s *Scope) Lookup(rt *Runtime, k string) *Binding {
if rt.IsDebugMode() {
fmt.Printf("[DEBUG] Looking up '%s'\n", k)
}
v, ok := s.bindings[k]
if ok {
if rt.IsDebugMode() {
fmt.Printf("[DEBUG] Found '%s': '%s'\n", k, v.Value.String())
}
return &v
}
if s.parent != nil {
return s.parent.Lookup(rt, k)
}
builtin := rt.LookupBuiltin(k)
if builtin != nil {
if rt.IsDebugMode() {
fmt.Printf("[DEBUG] Found builtin '%s': '%s'\n", k, builtin)
}
return &Binding{builtin, true}
}
return nil
}
func (s *Scope) Insert(k string, v IExpr, public bool) {
s.bindings[k] = Binding{Value: v, Public: public}
}
func (s *Scope) GetNS(rt *Runtime) *Namespace {
if s.ns == nil {
panic("A scope with no namespace !!!!")
}
ns, ok := rt.GetNS(*s.ns)
if !ok {
panic(fmt.Sprintf("A scope with the wrong namespace! '%s'", *(s.ns)))
}
return ns
}
func (s *Scope) SetNS(ns *string) {
s.ns = ns
}
func MakeScope(rt *Runtime, parent *Scope, namespace *string) *Scope {
var belongsTo *string
if parent != nil {
nsName := parent.GetNS(rt).GetName()
belongsTo = &nsName
} else if namespace == nil {
panic("When the 'parent' is nil, you have to provide the 'namespace' name.")
} else {
belongsTo = namespace
}
return &Scope{
parent: parent,
bindings: map[string]Binding{},
ns: belongsTo,
}
}

View File

@ -1,156 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
import (
"fmt"
"serene-lang.org/bootstrap/pkg/ast"
)
// Def defines a global binding in the current namespace. The first
// arguments in `args` has to be a symbol ( none ns qualified ) and
// the second param should be the value of the binding
func Def(rt *Runtime, scope IScope, args *List) (IExpr, IError) {
// TODO: Add support for docstrings and meta
if args.Count() == 2 {
name := args.First()
if name.GetType() != ast.Symbol {
return nil, MakeError(rt, name, "the first argument of 'def' has to be a symbol")
}
sym := name.(*Symbol)
valueExpr := args.Rest().First()
value, err := EvalForms(rt, scope, valueExpr)
if err != nil {
return nil, err
}
if value.GetType() == ast.Fn {
value.(*Function).SetName(sym.GetName())
}
ns := rt.CurrentNS()
ns.DefineGlobal(sym.GetName(), value, true)
return sym, nil
}
return nil, MakeError(rt, args, "'def' form need at least 2 arguments")
}
// Def defines a macro in the current namespace. The first
// arguments in `args` has to be a symbol ( none ns qualified ) and
// the rest of params should be the body of the macro. Unlike other
// expressions in Serene `defmacro` DOES NOT evaluate its arguments.
// That is what makes macros great
func DefMacro(rt *Runtime, scope IScope, args *List) (IExpr, IError) {
// TODO: Add support for docstrings and meta
if args.Count() < 2 {
return nil, MakeError(rt, args, "'defmacro' form need at least 2 arguments")
}
name := args.Rest().First()
if name.GetType() != ast.Symbol {
return nil, MakeError(rt, name, "the first argument of 'defmacro' has to be a symbol")
}
sym := name.(*Symbol)
var params IColl
body := MakeEmptyBlock()
arguments := args.Rest().Rest().First()
// TODO: Add vector in here
// Or any other icoll
if arguments.GetType() == ast.List {
params = arguments.(IColl)
}
if args.Count() > 2 {
body.SetContent(args.Rest().Rest().Rest().(*List).ToSlice())
}
macro := MakeMacro(scope, sym.GetName(), params, body)
ns := scope.GetNS(rt)
ns.DefineGlobal(sym.GetName(), macro, true)
return macro, nil
}
// Fn defines a function inside the given scope `scope` with the given `args`.
// `args` contains the argument list, docstring and body of the function.
func Fn(rt *Runtime, scope IScope, args *List) (IExpr, IError) {
if args.Count() < 2 {
return nil, MakeError(rt, args, "'fn' needs at least an arguments list")
}
var params IColl
body := MakeEmptyBlock()
arguments := args.Rest().First()
// TODO: Add vector in here
// Or any other icoll
if arguments.GetType() == ast.List {
params = arguments.(IColl)
}
if args.Count() > 1 {
body.SetContent(args.Rest().Rest().(*List).ToSlice())
}
return MakeFunction(MakeNodeFromExpr(args.First()), scope, params, body), nil
}
func NSForm(rt *Runtime, scope IScope, args *List) (IExpr, IError) {
if args.Count() == 1 {
return nil, MakeError(rt, args, "namespace's name is missing")
}
name := args.Rest().First()
if name.GetType() != ast.Symbol {
return nil, MakeError(rt, name, "the first argument to the 'ns' has to be a symbol")
}
nsName := name.(*Symbol).GetName()
if nsName != rt.CurrentNS().GetName() {
return nil, MakeError(
rt,
args,
fmt.Sprintf("the namespace '%s' doesn't match the file name.", nsName),
)
}
ns, ok := rt.GetNS(nsName)
if !ok {
return nil, MakeError(rt, name, fmt.Sprintf("can't find the namespace '%s'. Is it the same as the file name?", nsName))
}
return ns, nil
// TODO: Handle the params like `require` and `meta`
// params := args.Rest().Rest()
}

View File

@ -1,72 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
import (
"fmt"
"strings"
"serene-lang.org/bootstrap/pkg/ast"
"serene-lang.org/bootstrap/pkg/hash"
)
type String struct {
Node
ExecutionScope
content string
}
func (s *String) GetType() ast.NodeType {
return ast.String
}
func (s *String) String() string {
return "\"" + s.Escape() + "\""
}
func (s *String) PrintToString() string {
return s.content
}
func (s *String) ToDebugStr() string {
return fmt.Sprintf("<%s at %p>", s.content, s)
}
func (s *String) Hash() uint32 {
bytes := []byte(s.content)
return hash.Of(append([]byte{byte(ast.String)}, bytes...))
}
func (s *String) Escape() string {
replacer := strings.NewReplacer(
"\n", "\\n",
"\t", "\\t",
"\r", "\\r",
"\\", "\\\\",
"\"", "\\\"",
)
return replacer.Replace(s.content)
}
func MakeString(n Node, s string) *String {
return &String{
Node: n,
content: s,
}
}

View File

@ -1,96 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
import (
"strings"
"serene-lang.org/bootstrap/pkg/ast"
"serene-lang.org/bootstrap/pkg/hash"
)
type Symbol struct {
Node
ExecutionScope
name string
nsPart string
}
func (s *Symbol) GetType() ast.NodeType {
return ast.Symbol
}
func (s *Symbol) String() string {
if s.IsNSQualified() {
return s.nsPart + "/" + s.name
}
return s.name
}
func (s *Symbol) GetName() string {
return s.name
}
func (s *Symbol) GetNSPart() string {
return s.nsPart
}
func (s *Symbol) ToDebugStr() string {
return s.String()
}
func (s *Symbol) Hash() uint32 {
// TODO: Return a combined hash of nsPart and name
return hash.Of([]byte(s.nsPart + "/" + s.name))
}
func (s *Symbol) IsRestable() bool {
// Weird name ? I know :D
return strings.HasPrefix(s.name, "&")
}
func (s *Symbol) IsNSQualified() bool {
return s.nsPart != ""
}
func MakeSymbol(n Node, s string) (*Symbol, IError) {
parts := strings.Split(s, "/")
var (
name string
nsPart string
)
switch len(parts) {
case 1:
name = parts[0]
nsPart = ""
case 2:
name = parts[1]
nsPart = parts[0]
default:
return nil, MakeSyntaxErrorf(n, "can't create a symbol from '%s'. More that on '/' is illegal.", s)
}
return &Symbol{
Node: n,
name: name,
nsPart: nsPart,
}, nil
}

View File

@ -1,173 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package core
import (
"fmt"
"serene-lang.org/bootstrap/pkg/ast"
"serene-lang.org/bootstrap/pkg/hash"
)
// IRepresentable is the interface which any value that wants to have a string
// representation has to implement. Serene will use this string where ever
// it needs to present a value as string.
type IRepresentable interface {
fmt.Stringer
}
// IPrintable is the interface which any value that wants to have a string
// representation for printing has to implement. The `print` family functions will use
// this interface to convert forms to string first and if the value doesn't
// implement this interface they will resort to `IRepresentable`
type IPrintable interface {
IRepresentable
PrintToString() string
}
// IScopable is the interface describing how to get the execution scope of
// the value. During the evaluation of the forms in Serene we might rewrite
// the execution tree to eliminate tail calls. In order to do that we should
// be able to attach the execution scope to any form that we need to rewrite.
type IScopable interface {
// GetExecutionScope returns an attached execution scope if there's
// any, nil otherwise.
GetExecutionScope() IScope
// SetExecutionScope sets the given scope as the execution scope of
// the current implementor
SetExecutionScope(scope IScope)
}
// IDebuggable is the interface designed for converting forms to a string
// form which are meant to be used as debug data
type IDebuggable interface {
ToDebugStr() string
}
// IExpr is the most important interface in Serene which basically represents
// a VALUE in Serene. All the forms (beside special formss) has to implement
// this interface.
type IExpr interface {
ast.ILocatable
ast.ITypable
hash.IHashable
IRepresentable
IDebuggable
IScopable
}
// TODO: Add helper functions to reach methods on Node.location. For example
// Node.location.DecStart() has to have a helper on the Node like:
// Node.DecStartLocation
// Node struct is simply representing a Node in the AST which provides the
// functionalities required to trace the code based on the location.
type Node struct {
location ast.Location
}
// GetLocation returns the location of the Node in the source input
func (n Node) GetLocation() *ast.Location {
return &n.location
}
type ExecutionScope struct {
scope IScope
}
func (e *ExecutionScope) GetExecutionScope() IScope {
return e.scope
}
func (e *ExecutionScope) SetExecutionScope(scope IScope) {
e.scope = scope
}
// Helper functions ===========================================================
// changeExecutionScope sets the execution scope of all the expressions in `es`
// to the given `scope`
func changeExecutionScope(es []IExpr, scope IScope) {
for _, x := range es {
x.SetExecutionScope(scope)
}
}
// toRepresentables converts the given collection of IExprs to an array of
// IRepresentable. Since golangs type system is weird ( if A is an interface
// that embeds interface B you []A should be usable as []B but that's not the
// case in Golang), we need this convertor helper
func toRepresentables(forms IColl) []IRepresentable {
var params []IRepresentable
for _, x := range forms.ToSlice() {
params = append(params, x)
}
return params
}
// TODO: I don't like the current interface and signatures of these
// 'Make*Node*' functions. Refactor them to have the same interface
// For instance if we need to return a pointer to a Node all of them
// has to return a pointer not just one of them. The return type
// should be predictable
// MakeNodeFromLocation creates a new Node for the given Location `loc`
func MakeNodeFromLocation(loc *ast.Location) Node {
return Node{
location: *loc,
}
}
// MakeNodeFromExpr creates a new Node from the given `ILocatable`.
// We use the Node to pass it to other IExpr constructors to
// keep the reference to the original form in the input string
func MakeNodeFromExpr(e ast.ILocatable) Node {
return MakeNodeFromLocation(e.GetLocation())
}
// MakeNodeFromExprs creates a new Node from the given slice of `IExpr`s.
// We use the Node to pass it to other IExpr constructors to
// keep the reference to the original form in the input string
func MakeNodeFromExprs(es []IExpr) *Node {
if len(es) == 0 {
return nil
}
firstLoc := es[0].GetLocation()
endLoc := es[len(es)-1].GetLocation()
loc := ast.MakeLocation(firstLoc.GetSource(), firstLoc.GetStart(), endLoc.GetEnd())
n := MakeNodeFromLocation(loc)
return &n
}
// MakeNode creates a new Node in the the given `input` that points to a
// range of characters starting from the `start` till the `end`.
func MakeNode(input *ast.Source, start, end int) Node {
return MakeNodeFromLocation(ast.MakeLocation(input, start, end))
}
// MakeSinglePointNode creates a not the points to a single char in the
// input
func MakeSinglePointNode(input *ast.Source, point int) Node {
return MakeNode(input, point, point)
}

View File

@ -1,84 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Package dl provides the necessary interface to interact with share
// libraries
package dl
/*
#cgo linux LDFLAGS: -ldl
#cgo pkg-config: libffi
#include <dlfcn.h>
#include <limits.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
static uintptr_t openShareLib(const char* path, char** err) {
void* h = dlopen(path, RTLD_NOW|RTLD_GLOBAL);
if (h == NULL) {
*err = (char*)dlerror();
}
return (uintptr_t)h;
}
static void* shareLibLookup(uintptr_t h, const char* name, char** err) {
void* r = dlsym((void*)h, name);
if (r == NULL) {
*err = (char*)dlerror();
}
return r;
}
*/
// import "C"
// import (
// "fmt"
// "unsafe"
// )
// type SharedLib struct{}
// func Open(libPath string) (*SharedLib, error) {
// cPath := make([]byte, C.PATH_MAX+1)
// cRelName := make([]byte, len(libPath)+1)
// copy(cRelName, libPath)
// // If the given libPath exists, fill the cPath with the absolute path
// // to the file (it follows symlinks).
// if C.realpath(
// (*C.char)(unsafe.Pointer(&cRelName[0])),
// (*C.char)(unsafe.Pointer(&cPath[0]))) == nil {
// return nil, fmt.Errorf("can't find the shared library '%s'", libPath)
// }
// var cErr *C.char
// h := C.openShareLib((*C.char)(unsafe.Pointer(&cPath[0])), &cErr)
// if h == 0 {
// // lock.Unlock()
// return nil, fmt.Errorf("failed to open shared library: '%s' due to: '%s'", libPath, C.GoString(cErr))
// }
// initTask := C.shareLibLookup(h, C.CString("bar"), &cErr)
// fmt.Printf(">> %p \n", initTask)
// return &SharedLib{}, nil
// }

View File

@ -1,71 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Package errors is dedicated to hold the error numbers and description of
// each knowen error in Serene
package errors
type Errno uint
const (
E0000 Errno = iota // THE DESCRIPTION IS NOT SET
E0001
E0002
E0003
)
func (e Errno) String() string {
return [...]string{
"E0000",
"E0001",
"E0002",
"E0003",
}[e]
}
var ErrorsDescription map[Errno]string = map[Errno]string{
E0000: `Can't find any description for this error.`,
E0001: `
Namespaces are fundamental units in Serene. Each file has to start with
a namespace declaration with a name that matches the path of the file.
For example imagine haivng a file with the following path
'/home/user/xyz/src/example/abc.srn' and '/home/user/xyz/src' is
in the load path. The namespace path to the file would be 'example.abc' so
that file has to contain a 'ns' form as the first expression with
'example.abc' as the name just like:
(ns example.abc)
...rest of the file...
Since comments are not expressions it's ok to start a file by comments
followed by the 'ns' form`,
E0002: `
Functions expect a certain number of argument. The number of arguments
that you're passing to the function doesn't match with it's signature.
To fix the problem double check the function signature and make sure
that you're passing the correct number of arguments to it`,
E0003: `
Do you have a typo ? Or did you forget to define a symbol that you're trying
to evaluate ?
This error happens when the symbol that you're trying to evaluate is not
associated with any value in the current scope tree.
`,
}

View File

@ -1,48 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Package hash provides the hashing functionality
package hash
import "hash/crc32"
var hashTable *crc32.Table = crc32.MakeTable(crc32.Castagnoli)
// IHashable is the interface types which allows expressions to have a hash
// value that doesn't change through out their life time. The origin
// of each expression can be checked by comparing their hashes. Basically
// two expressions with the same hash consider to be the same.
type IHashable interface {
// Returns a 32 bit hash of the the entity which implements it.
// The hash should be constant to the life time of the implementor.
Hash() uint32
}
func Of(in []byte) uint32 {
return crc32.Checksum(in, hashTable)
}
// CombineHashes combines two hashes and return a new one
func CombineHashes(hash1, hash2 uint32) uint32 {
// This way of composing hashes is used in libboost and almost everyone
// is using it. The 0x9e3779b9 is the integral part of the Golden Ratio's
// fractional part 0.61803398875… (sqrt(5)-1)/2, multiplied by 2^32.
// For more info: https://lkml.org/lkml/2016/4/29/838
hash1 ^= hash2 + 0x9e3779b9 + (hash1 << 6) + (hash2 >> 2)
return hash1
}

View File

@ -1,25 +0,0 @@
/*
Serene --- Yet an other Lisp
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package main
import "serene-lang.org/bootstrap/cmd"
func main() {
cmd.Execute()
}

View File

@ -1,4 +0,0 @@
(print 4)
(print -43)
(print 3.4)
(println asd)