Remove the goimpl and move it to a separate branch
This commit is contained in:
parent
202f041515
commit
38089606c1
|
@ -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)
|
||||
|
|
|
@ -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....'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
14
Makefile
14
Makefile
|
@ -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
|
|
@ -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
|
|
@ -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"]
|
|
@ -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.
|
|
@ -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
|
|
@ -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).
|
|
@ -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)
|
||||
}
|
|
@ -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.")
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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")
|
|
@ -1,5 +0,0 @@
|
|||
foo:
|
||||
gcc -c -Wall -Werror -fpic foo.c
|
||||
gcc -shared -o libfoo.so foo.o
|
||||
|
||||
all: foo
|
|
@ -1,7 +0,0 @@
|
|||
#include <stdio.h>
|
||||
|
||||
|
||||
void bar(void)
|
||||
{
|
||||
puts("Hello, I am a shared library");
|
||||
}
|
|
@ -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.
|
@ -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")))
|
|
@ -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
|
||||
)
|
637
bootstrap/go.sum
637
bootstrap/go.sum
|
@ -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=
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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"
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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()))
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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))
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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{},
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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{},
|
||||
}
|
||||
}
|
|
@ -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}
|
||||
}
|
|
@ -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) {}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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()))
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
// }
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
// }
|
|
@ -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.
|
||||
`,
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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()
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
(print 4)
|
||||
(print -43)
|
||||
(print 3.4)
|
||||
(println asd)
|
Loading…
Reference in New Issue