Compare commits

..

2 Commits
master ... ep13

172 changed files with 11950 additions and 6575 deletions

View File

@ -16,7 +16,7 @@ AlignEscapedNewlines: Left
AlwaysBreakTemplateDeclarations: Yes
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^"'
- Regex: '^"(serene)/'
Priority: 1
SortPriority: 1
CaseSensitive: true

View File

@ -1,6 +1,6 @@
---
Checks: '-*,clang-diagnostic-*,clang-analyzer-*,cert-*,-cert-err58-cpp,concurrency-*,llvm-*,performance-*,readability-*,-readability-identifier-length*'
WarningsAsErrors: '-*,clang-diagnostic-*,clang-analyzer-*,cert-*,-cert-err58-cpp,concurrency-*,llvm-*,performance-*,readability-*,-readability-identifier-length*'
Checks: 'clang-diagnostic-*,clang-analyzer-*,-*,clang-analyzer-*,cert-*,-cert-err58-cpp,concurrency-*,llvm-*,performance-*,readability-*'
WarningsAsErrors: 'clang-diagnostic-*,clang-analyzer-*,-*,clang-analyzer-*,cert-*,-cert-err58-cpp,concurrency-*,llvm-*,performance-*,readability-*'
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
FormatStyle: file

View File

@ -1,2 +0,0 @@
./resources/

12
.gitignore vendored
View File

@ -23,14 +23,4 @@ bin/serenec_CXX_cotire.cmake
/config.h
docs/Doxyfile.docs
.ccache/
docs/spec.tex
docs/spec.pdf
.tmp
.env
.tex
.pdf
docs/overall_picture.png
.direnv/
.pre-commit-config.yaml
.envrc
.ccache/

0
.gitmodules vendored
View File

View File

@ -1 +1 @@
#leak:mlir::Region::emplaceBlock
#leak:mlir::Region::emplaceBlock

View File

@ -1,55 +0,0 @@
pipeline:
Linters:
group: build
image: lxsameer/serene_ci:13
commands:
- export SERENE_CI=true
- ./builder setup
- export FILES="$(git diff --name-only HEAD HEAD~1)"
- pre-commit run --files "$FILES"
Build:
group: build
image: lxsameer/serene_ci:13
commands:
# Uncomment this when running with a new toolchain for the
# first time to save up space
# - rm -rf /root/.serene/*
- ./builder build -DSERENE_DISABLE_CCACHE=ON
volumes:
- serene_config:/root/.serene/
ChatNotify:
image: lxsameer/notify:3
settings:
matrix_room_id:
from_secret: matrix_room
matrix_access_token:
from_secret: matrix_token
matrix_user:
from_secret: matrix_user
matrix_msg: "[${CI_REPO}][Build] Job #${CI_BUILD_NUMBER} <b>failed</b> for branch <b>${CI_COMMIT_BRANCH}</b>. ${CI_BUILD_LINK}"
secrets: [ matrix_room, matrix_token, matrix_user ]
when:
- status: [failure]
MailNotify:
image: lxsameer/woodpecker_mailer:4
settings:
from: ci@serene-lang.org
user:
from_secret: mailer_user
password:
from_secret: mailer_password
to: ${CI_COMMIT_AUTHOR_EMAIL}
subject: "[${CI_REPO}][Build] JOB #${CI_BUILD_NUMBER} failed for branch '${CI_COMMIT_BRANCH}'."
text: |
BUILD: ${CI_BUILD_LINK}
COMMIT: ${CI_COMMIT_LINK}
when:
- status: [failure]
secrets: [ mail_pass, mail_user ]

View File

@ -1,64 +0,0 @@
pipeline:
build:
image: woodpeckerci/plugin-docker-buildx
secrets: [docker_username, docker_password]
settings:
repo: serenelang/serene-docs
registry: docker.io
dockerfile: docs/Dockerfile
tags: latest
username:
from_secret: docker_username
password:
from_secret: docker_password
when:
- path:
include: [ 'mkdocs.yml', 'docs/**' ]
- branch: master
deploy:
image: docker:24.0.2-cli-alpine3.18
commands:
- docker stack deploy -c docs/service.yml serene-docs --prune
volumes:
- /var/run/docker.sock:/var/run/docker.sock
when:
- path:
include: [ 'mkdocs.yml', 'docs/**' ]
# ignore_message: "[ALL]"
- branch: master
ChatNotify:
image: lxsameer/notify:3
settings:
matrix_room_id:
from_secret: matrix_room
matrix_access_token:
from_secret: matrix_token
matrix_user:
from_secret: matrix_user
matrix_msg: "[${CI_REPO}][Docs] Job #${CI_BUILD_NUMBER} <b>failed</b> for branch <b>${CI_COMMIT_BRANCH}</b>. ${CI_BUILD_LINK}"
secrets: [ matrix_room, matrix_token, matrix_user ]
when:
- status: [failure]
MailNotify:
image: lxsameer/woodpecker_mailer:4
settings:
from: ci@serene-lang.org
user:
from_secret: mailer_user
password:
from_secret: mailer_password
to: ${CI_COMMIT_AUTHOR_EMAIL}
subject: "[${CI_REPO}][Docs] JOB #${CI_BUILD_NUMBER} failed for branch '${CI_COMMIT_BRANCH}'."
text: |
BUILD: ${CI_BUILD_LINK}
COMMIT: ${CI_COMMIT_LINK}
when:
- status: [failure]
secrets: [ mail_pass, mail_user ]

View File

@ -1,61 +1,55 @@
# Serene Programming Language
#
# Copyright (c) 2019-2024 Sameer Rahmani <lxsameer@gnu.org>
# Copyright (c) 2019-2021 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, version 2.
# 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, version 2.
#
# 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.
# 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/>.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
cmake_minimum_required(VERSION 3.19)
project(
Serene
VERSION 1.0.0
DESCRIPTION "A modern typed Lisp."
# Project name and a few useful settings. Other commands can pick up the results
project(Serene
VERSION 0.1.0
DESCRIPTION "Serene language is a modern Lisp."
LANGUAGES CXX C)
# Clangd command file
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
# =============================================================================
# Policies
# =============================================================================
cmake_policy(SET CMP0116 OLD)
# Policies ==========================
cmake_policy(SET CMP0116 NEW)
# =============================================================================
# User Options
# =============================================================================
option(CPP_20_SUPPORT "C++20 Support" ON)
option(SERENE_BUILD_TESTING "Enable tests" ON)
# User Options ======================
option(CPP_20_SUPPORT "C++20 Support" OFF)
option(SERENE_BUILD_TESTING "Enable tests" OFF)
option(SERENE_ENABLE_BUILDID "Enable build id." OFF)
option(SERENE_ENABLE_THINLTO "Enable ThisLTO." ON)
option(SERENE_ENABLE_DOCS "Enable document generation" OFF)
option(SERENE_ENABLE_TIDY "Enable clang tidy check" OFF)
option(SERENE_DISABLE_CCACHE "Disable automatic ccache integration" OFF)
option(SERENE_ENABLE_DEVTOOLS "Enable the devtools build" OFF)
option(SERENE_DISABLE_MUSL "Disable musl libc (Musl is recommended)." OFF)
option(SERENE_DISABLE_LIBCXX "Disable libc++ (libc++ is recommended)." OFF)
option(SERENE_DISABLE_COMPILER_RT
"Disable compiler-rt (compiler-rt is recommended)." OFF)
# LLVM Info about the target llvm build
option(LLVM_USE_PERF "If the target LLVM build is built with LLVM_USE_PERF" OFF)
# libserene
option(SERENE_SHARED_LIB "Build libserene as a shared library" ON)
option(SERENE_SHOW_MLIR_DIALECTS "Print out a list of MLIR dialect libs" OFF)
option(SERENE_SHOW_MLIR_TRANSFORMERS "Print out a list of MLIR dialect transformer libs" OFF)
option(SERENE_SHOW_LLVM_LIBS "Print all the llvm libs available" OFF)
# Only do these if this is the main project, and not if it is included through
# add_subdirectory
option(SERENE_WITH_MLIR_CL_OPTION "Add support for controlling MLIR via command line options" OFF)
# Only do these if this is the main project, and not if it is included through add_subdirectory
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
# Settings =======================
set(C_STANDARD 17)
## Settings =======================
# specify the C++ standard
if(CPP_20_SUPPORT)
if (CPP_20_SUPPORT)
set(CMAKE_CXX_STANDARD 20)
else()
set(CMAKE_CXX_STANDARD 17)
@ -63,21 +57,22 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# Setup the source locations
set(INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include)
set(SRC_DIR ${CMAKE_SOURCE_DIR}/src)
if(SERENE_ENABLE_TIDY)
find_program(CLANG_TIDY_PATH NAMES clang-tidy REQUIRED)
endif()
# We use iwyu intensively. For the version details check out the submodule at
# `deps/include-what-you-use`
find_program(iwyu NAMES include-what-you-use iwyu REQUIRED)
set(iwyu_path ${iwyu})
# Let's ensure -std=c++xx instead of -std=g++xx
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/scripts/cmake")
set(MemoryCheckCommand "valgrind")
configure_file(${INCLUDE_DIR}/serene/config.h.in include/serene/config.h)
# Let's nicely support folders in IDEs
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
@ -86,122 +81,149 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
-Wall
-Wextra
-Werror
-Wpedantic
-Wabstract-final-class
-Walloca
-Warray-bounds-pointer-arithmetic
-Warray-parameter
-Wassign-enum
-Wsign-conversion
-Wnon-virtual-dtor
-Wold-style-cast
-Wcast-align
-Wunused
-Woverloaded-virtual
-Wdouble-promotion
-Wformat=2)
-fno-rtti
-fno-builtin-strlen
# Dedicate a section to each function, so the linker
# can do a better job on dead code elimination
-ffunction-sections
-fdata-sections
$<$<CONFIG:DEBUG>:-g3>
$<$<CONFIG:DEBUG>:-ggdb>
# For the sake of debugging
$<$<CONFIG:DEBUG>:-fno-inline>
# To make the local ccache happy
$<$<CONFIG:DEBUG>:-fdebug-prefix-map=${PROJECT_SOURCE_DIR}=.>
$<$<CONFIG:DEBUG>:-fno-omit-frame-pointer>
$<$<CONFIG:RELEASE>:-fomit-frame-pointer>
$<$<CONFIG:DEBUG>:-fsanitize=address>
$<$<CONFIG:RELEASE>:-O3>
$<$<CONFIG:RELEASE>:-fmerge-all-constants>
$<$<CONFIG:RELEASE>:-flto=thin>
$<$<CONFIG:DEBUG>:-shared-libsan>
)
add_link_options(
# We enforce the lld linker
-fuse-ld=lld
-Wl,-gc-sections
$<$<CONFIG:DEBUG>:-shared-libsan>
$<$<CONFIG:RELEASE>:-fsanitize-address-globals-dead-stripping>
$<$<CONFIG:DEBUG>:-fsanitize=address>
$<$<CONFIG:RELEASE>:-flto=thin>
$<$<CONFIG:RELEASE>:-s>
# Do not link against shared libraries
#--static
)
# Do we need to build serene as a shared lib? default is "yes"
if(SERENE_SHARED_LIB)
set(BUILD_SHARED_LIBS "${SERENE_SHARED_LIB}")
endif()
find_program(LLD_PROGRAM REQUIRED NAMES lld)
find_program(MLIRTBLGEN_PROGRAM REQUIRED NAMES mlir-tblgen)
if(SERENE_ENABLE_BUILDID)
add_link_options(-Wl,--build-id)
endif()
#TODO: Setup the THINLTO on release
if(SERENE_ENABLE_THINLTO)
endif()
# CCache support ==============================
if(SERENE_DISABLE_CCACHE)
message(STATUS "CCache support is disabled")
else()
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
message(STATUS "Found CCache")
set(SERENE_CCACHE_MAXSIZE
""
CACHE STRING "Size of ccache")
set(SERENE_CCACHE_DIR
""
CACHE STRING "Directory to keep ccached data")
set(SERENE_CCACHE_PARAMS
"CCACHE_CPP2=yes CCACHE_HASHDIR=yes"
CACHE STRING "Parameters to pass through to ccache")
set(SERENE_CCACHE_MAXSIZE "" CACHE STRING "Size of ccache")
set(SERENE_CCACHE_DIR "" CACHE STRING "Directory to keep ccached data")
set(SERENE_CCACHE_PARAMS "CCACHE_CPP2=yes CCACHE_HASHDIR=yes"
CACHE STRING "Parameters to pass through to ccache")
set(CCACHE_PROGRAM "${SERENE_CCACHE_PARAMS} ${CCACHE_PROGRAM}")
if(SERENE_CCACHE_MAXSIZE)
set(CCACHE_PROGRAM
"CCACHE_MAXSIZE=${SERENE_CCACHE_MAXSIZE} ${CCACHE_PROGRAM}")
if (SERENE_CCACHE_MAXSIZE)
set(CCACHE_PROGRAM "CCACHE_MAXSIZE=${SERENE_CCACHE_MAXSIZE} ${CCACHE_PROGRAM}")
endif()
if(SERENE_CCACHE_DIR)
if (SERENE_CCACHE_DIR)
set(CCACHE_PROGRAM "CCACHE_DIR=${SERENE_CCACHE_DIR} ${CCACHE_PROGRAM}")
endif()
message(STATUS "Using CCACHE: ${CCACHE_PROGRAM}")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_PROGRAM})
else()
message(
FATAL_ERROR
"Unable to find the program ccache. Set SERENE_DISABLE_CCACHE to ON")
message(FATAL_ERROR "Unable to find the program ccache. Set SERENE_DISABLE_CCACHE to ON")
endif()
endif()
if(SERENE_BUILD_TESTING)
enable_testing()
find_package(GTest REQUIRED)
# For Windows: Prevent overriding the parent project's compiler/linker
# settings
set(gtest_force_shared_crt
ON
CACHE BOOL "" FORCE)
endif()
add_link_options(-Wl,-Map=output.map)
# LLVM setup
# ================================================================== Why not
# specify the version? Since we use the development version of the LLVM all
# the time it doesn't make sense to use a version here
# LLVM setup =========================================
find_package(LLVM REQUIRED CONFIG)
find_package(MLIR REQUIRED CONFIG)
find_package(LLD REQUIRED CONFIG)
find_program(LLD_PROGRAM REQUIRED NAMES lld)
find_program(MLIRTBLGEN_PROGRAM REQUIRED NAMES mlir-tblgen)
find_package(Clang REQUIRED CONFIG)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
message(STATUS "Using MLIRConfig.cmake in: ${MLIR_DIR}")
message(STATUS "Using LLDConfig.cmake in: ${LLD_DIR}")
message(STATUS "Using CLANGConfig.cmake in: ${Clang_DIR}")
set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/bin)
set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/lib)
set(MLIR_BINARY_DIR ${CMAKE_BINARY_DIR})
# Make cmake modules available to load
list(APPEND CMAKE_MODULE_PATH "${MLIR_DIR}")
list(APPEND CMAKE_MODULE_PATH "${LLVM_DIR}")
list(APPEND CMAKE_MODULE_PATH "${LLD_DIR}")
list(APPEND CMAKE_MODULE_PATH "${Clang_DIR}")
list(APPEND CMAKE_MODULE_PATH "${MLIR_CMAKE_DIR}")
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}")
list(APPEND CMAKE_MODULE_PATH "${LLD_CMAKE_DIR}")
include(TableGen)
include(AddLLVM)
include(AddMLIR)
include(HandleLLVMOptions)
include(AddClang)
# This goes against the CMake's best practices to add these kind of settings
# to the targets only. But this is what LLVM recommends and we will stick to
# their recommendation.
include_directories(SYSTEM ${LLVM_INCLUDE_DIRS})
separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS})
add_definitions(${LLVM_DEFINITIONS_LIST})
link_directories(${LLVM_BUILD_LIBRARY_DIR})
add_definitions(${LLVM_DEFINITIONS})
# /LLVM setup
# =================================================================
# add_subdirectory(serene-tblgen)
add_subdirectory(serene)
# include(tablegen-serene) Create the tools we use to compile Serene
llvm_map_components_to_libnames(llvm_libs support)
# The compiled library code is here add_subdirectory(libserene) The static
# library containing builtin special forms and functions
# add_subdirectory(core) Binary tools of the compiler
# add_subdirectory(serenec) add_subdirectory(serene-repl)
# add_subdirectory(devtools)
if(SERENE_ENABLE_DOCS)
add_subdirectory(docs)
# Serene Setup ===================================
include_directories(${PROJECT_SOURCE_DIR}/include)
# We don't want the generated files from table gen
# to be treated as local since the contain warnings
include_directories(SYSTEM ${PROJECT_BINARY_DIR}/include)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/include/)
# The compiled library code is here
add_subdirectory(src)
# The executable code is here
add_subdirectory(include)
if (SERENE_ENABLE_DOCS)
# Docs only available if this is the main app
find_package(Doxygen
REQUIRED dot
OPTIONAL_COMPONENTS dia)
if(Doxygen_FOUND)
add_subdirectory(docs)
else()
message(STATUS "Doxygen not found, not building docs")
endif()
endif()
endif()

0
LICENSE Normal file → Executable file
View File

View File

@ -1,33 +0,0 @@
# Serene lang
[![Please don't upload to GitHub](https://nogithub.codeberg.page/badge.svg)](https://nogithub.codeberg.page)
[![status-badge](https://ci.devheroes.codes/api/badges/Serene/serene/status.svg)](https://ci.devheroes.codes/Serene/serene)
Serene is a modern typed lisp. It's not done yet, and it's heavily under development. Don't
expect anything stable for now.
## More Info
- Website: https://serene-lang.org
- Documentation: https://serene-lang.org/getting_started/
- CI: https://ci.devheroes.codes/Serene/serene
# Get Help
If you need help, or you just want to hang out, you can find us at:
- *IRC*: *#serene-lang* on the libera chat server
- *Matrix*: https://app.element.io/#/room/#serene:matrix.org
- *MailingList*: https://www.freelists.org/list/serene
# License
Copyright (c) 2019-2024 Sameer Rahmani <lxsameer@gnu.org>
*Serene* 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, version 2.
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/>.

101
README.org Normal file
View File

@ -0,0 +1,101 @@
* Serene lang
** Setup development environment
Setup the githook and install dependencies using the following commands:
#+BEGIN_SRC bash
./builder setup
#+END_SRC
*** Dependencies
You would need the following dependencies to start get started with *Serene* development
- LLVM (LLVM Instructions coming up.)
- cmake
- ninja
- doxygen (If you want to build the docs as well)
- Valgrind
- CCache (If you want faster builds specially with the LLVM)
** LLVM Installation
MLIR is a part of the [[https://llvm.org][LLVM]] project and in order to build it we need to build the LLVM itself as well.
Here is a quick guide to build the latest version of the LLVM and MLIR.
#+BEGIN_SRC bash
## YES we're using the development version of MLIR
git clone https://github.com/llvm/llvm-project.git
mkdir llvm-project/build
cd llvm-project/build
cmake -G Ninja ../llvm \
-DCMAKE_INSTALL_PREFIX=/your/target/path \
-DLLVM_PARALLEL_COMPILE_JOBS=7 \
-DLLVM_PARALLEL_LINK_JOBS=1 \
-DLLVM_BUILD_EXAMPLES=ON \
-DLLVM_TARGETS_TO_BUILD="X86" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_ASSERTIONS=ON \
-DLLVM_CCACHE_BUILD=ON \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DLLVM_ENABLE_PROJECTS='clang;lldb;lld;mlir;clang-tools-extra;compiler-rt' \
-DCMAKE_C_COMPILER=clang \ # If you have clang installed already
-DCMAKE_CXX_COMPILER=clang++ \ # If you have clang installed already
-DLLVM_ENABLE_LLD=ON
cmake --build .
cmake --build . --target check-mlir
cmake -DCMAKE_INSTALL_PREFIX=/your/target/location -P cmake_install.cmake
#+END_SRC
You need to have =clang= and =lld= installed to compile the LLVM with the above command. Also if you
are not using =ccache= just remove the option related to it from the above command.
*** Emacs
If you're using Emacs as your development environment just install =clangd= and =lsp=.
** Heads up for devs
While you're working on *Serene* be mindful of:
- In =DEBUG= mode we dynamically link against =libsan= due to the fact that we build the =libserene=
as a shared lib by default. This means we need to =LD_PRELOAD= the =libclang_rt= before we run
any executable. If you're using the =builder= script you're all set otherwise you can run an
executable like:
#+BEGIN_SRC bash
LD_PRELOAD=$(clang -print-file-name=libclang_rt.asan-x86_64.so) /path/to/executable
#+END_SRC
* How to build
In order to build for development (Debug mode) just use =./builder build= to setup the build and build
the project once and then you can just use =./builder compile= to build the changed files only.
Check out the =builder= script for more subcommands and details.
* Cheatsheets
- [[https://github.com/muqsitnawaz/modern-cpp-cheatsheet][Modern C++ Cheatsheet]]
* License
Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*Serene* 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, version 2.
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/>.
* Get Help
If you need help or you just want to hangout, you can find us at:
- *IRC*: *#serene-lang* on the freenode server
- *Matrix Network*: https://matrix.to/#/#serene:matrix.org?via=matrix.org&via=gitter.im
- *MailingList*: https://www.freelists.org/list/serene

232
builder Executable file
View File

@ -0,0 +1,232 @@
#! /bin/bash
# Serene Programming Language
#
# Copyright (c) 2019-2021 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, version 2.
#
# 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/>.
command=$1
export CC=$(which clang)
export CXX=$(which clang++)
# TODO: Add sloppiness to the cmake list file as well
export CCACHE_SLOPPINESS="pch_defines,time_macros"
export ASAN_OPTIONS=check_initialization_order=1
LSAN_OPTIONS=suppressions=$(pwd)/.ignore_sanitize
export LSAN_OPTIONS
export LDFLAGS="-fuse-ld=lld"
# The `builder` script is supposed to be run from the
# root of the source tree
ROOT_DIR=$(pwd)
BUILD_DIR=$ROOT_DIR/build
ME=$(cd "$(dirname "$0")/." >/dev/null 2>&1 ; pwd -P)
CMAKEARGS_DEBUG=" -DCMAKE_BUILD_TYPE=Debug -DSERENE_WITH_MLIR_CL_OPTION=ON"
CMAKEARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DSERENE_CCACHE_DIR=$HOME/.ccache"
# The scan-build utility scans the build for bugs checkout the man page
scanbuild="scan-build --force-analyze-debug-code --use-analyzer=$(which clang)"
function gen_precompile_header_index() {
echo "// DO NOT EDIT THIS FILE: It is aute generated by './builder gen_precompile_index'" > ./include/serene_precompiles.h
echo "#ifndef SERENE_PRECOMPIL_H" >> ./include/serene_precompiles.h
echo "#define SERENE_PRECOMPIL_H" >> ./include/serene_precompiles.h
grep -oP "#include .llvm/.*" . -R|cut -d':' -f2|tail +2 >> ./include/serene_precompiles.h
grep -oP "#include .mlir/.*" . -R|cut -d':' -f2|tail +2 >> ./include/serene_precompiles.h
echo "#endif" >> ./include/serene_precompiles.h
}
function pushed_build() {
pushd "$BUILD_DIR" > /dev/null || return
}
function popd_build() {
popd > /dev/null || return
}
function build-gen() {
pushed_build
echo "Running: "
echo "cmake -G Ninja $CMAKEARGS $CMAKEARGS_DEBUG \"$@\" \"$ROOT_DIR\""
cmake -G Ninja $CMAKEARGS $CMAKEARGS_DEBUG "$@" "$ROOT_DIR"
popd_build
}
function compile() {
pushed_build
cmake --build .
popd_build
}
function build() {
build-gen "$@"
pushed_build
cmake --build .
popd_build
}
function build-20() {
pushed_build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCPP_20_SUPPORT=ON "$@" "$ROOT_DIR"
cmake --build .
popd_build
}
function build-release() {
pushed_build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release "$ROOT_DIR"
cmake --build .
popd_build
}
function build-docs() {
pushed_build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Docs "$ROOT_DIR"
cmake --build .
popd_build
}
function clean() {
rm -rf "$BUILD_DIR"
}
function run() {
LD_PRELOAD=$(clang -print-file-name=libclang_rt.asan-x86_64.so) "$BUILD_DIR"/src/serenec/serenec "$@"
}
function repl() {
LD_PRELOAD=$(clang -print-file-name=libclang_rt.asan-x86_64.so) "$BUILD_DIR"/src/serene-repl/serene-repl "$@"
}
function memcheck() {
export ASAN_FLAG=""
build
pushed_build
valgrind --tool=memcheck --leak-check=yes --trace-children=yes "$BUILD_DIR"/bin/serenec "$@"
popd_build
}
function run-tests() {
LD_PRELOAD=$(clang -print-file-name=libclang_rt.asan-x86_64.so) "$BUILD_DIR"/src/tests/tests
}
function tests() {
pushed_build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON "$ROOT_DIR"
cmake --build .
popd_build
}
case "$command" in
"setup")
rm -rfv $ME/.git/hooks/pre-commit
ln -s $ME/scripts/pre-commit $ME/.git/hooks/pre-commit
;;
"build")
clean
mkdir -p "$BUILD_DIR"
build "${@:2}"
;;
"build-tidy")
clean
mkdir -p "$BUILD_DIR"
build "-DSERENE_ENABLE_TIDY=ON" "${@:2}"
;;
"build-20")
clean
mkdir -p "$BUILD_DIR"
build-20 "${@:2}"
;;
"build-docs")
clean
mkdir -p "$BUILD_DIR"
build-docs "${@:2}"
;;
"build-release")
clean
mkdir -p "$BUILD_DIR"
build-release "${@:2}"
;;
"compile")
compile
;;
"compile-and-tests")
compile
run-tests
;;
"run")
run "${@:2}"
;;
"repl")
repl "${@:2}"
;;
"run-tests")
run-tests "${@:2}"
;;
"scan-build")
clean
mkdir -p "$BUILD_DIR"
build-gen
pushed_build
exec $scanbuild cmake --build .
popd_build
;;
"memcheck")
memcheck "${@:2}"
;;
"tests")
clean
mkdir -p "$BUILD_DIR"
tests
run-tests
;;
"clean")
rm -rf "$BUILD_DIR"
;;
"gen_precompile_index")
gen_precompile_header_index
;;
"full-build")
clean
mkdir -p "$BUILD_DIR"
build
tests
run-tests
memcheck
;;
*)
echo "Commands: "
echo "setup - Setup the githooks for devs"
echo "full-build - Build and test Serene."
echo "build - Build Serene from scratch in DEBUG mode."
echo "build-release - Build Serene from scratch in RELEASE mode."
echo "compile - reCompiles the project using the already exist cmake configuration"
echo "compile-and-tests - reCompiles the project using the already exist cmake configuration and runs the tests"
echo "run - Runs the serene executable"
echo "scan-build - Compiles serene with static analyzer"
echo "tests - Runs the test cases"
echo "memcheck - Runs the memcheck(valgrind) tool."
echo "clean - :D"
;;
esac

View File

@ -1,29 +0,0 @@
# Serene Programming Language
#
# Copyright (c) 2019-2024 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, version 2.
#
# 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/>.
# This file sets up a CMakeCache to build serene for development. In this
# cache file we assume that you are using the toolchain and musl that are
# built by the `builder` script. For example: `builder deps build llvm`
# You still can just build everything yourself but the builder script and
# this file make the process easier.
# Where to find the packages. Packages can be built from source
# or downloaded via the builder script.
set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE BOOL "")
set(SERENE_CCACHE_DIR "$ENV{HOME}/.ccache" CACHE STRING "")
set(CMAKE_BUILD_TYPE "Debug")

View File

@ -1,29 +0,0 @@
# Serene Programming Language
#
# Copyright (c) 2019-2024 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, version 2.
#
# 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/>.
# This file sets up a CMakeCache to build serene for development. In this
# cache file we assume that you are using the toolchain and musl that are
# built by the `builder` script. For example: `builder deps build llvm`
# You still can just build everything yourself but the builder script and
# this file make the process easier.
# Where to find the packages. Packages can be built from source
# or downloaded via the builder script.
set(CMAKE_EXPORT_COMPILE_COMMANDS OFF CACHE BOOL "")
set(SERENE_CCACHE_DIR "$ENV{HOME}/.ccache" CACHE STRING "")
set(CMAKE_BUILD_TYPE "Release")

View File

@ -1,11 +0,0 @@
#Look for an executable called sphinx-build
find_program(SPHINX_EXECUTABLE
NAMES sphinx-build
DOC "Path to sphinx-build executable")
include(FindPackageHandleStandardArgs)
#Handle standard arguments to find_package like REQUIRED and QUIET
find_package_handle_standard_args(Sphinx
"Failed to find sphinx-build executable"
SPHINX_EXECUTABLE)

View File

@ -1,22 +0,0 @@
# Serene Programming Language
#
# Copyright (c) 2019-2024 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, version 2.
#
# 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/>.
function(serene_tablegen ofn)
tablegen(SERENE ${ARGV})
set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn}
PARENT_SCOPE)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
endfunction()

View File

@ -1,49 +0,0 @@
# Serene Programming Language
#
# Copyright (c) 2019-2024 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, version 2.
#
# 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/>.
# This file sets up a CMakeCache to build serene for development. In this
# cache file we assume that you are using the toolchain and musl that are
# built by the `builder` script. For example: `builder deps build llvm`
# You still can just build everything yourself but the builder script and
# this file make the process easier.
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR x86_64)
set(triple x86_64-pc-linux-musl)
set(CMAKE_SYSROOT ${SERENE_TOOLCHAIN_PATH})
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
set(CMAKE_C_COMPILER "clang")
set(CMAKE_C_COMPILER_AR "llvm-ar")
set(CMAKE_C_COMPILER_RANLIB "llvm-ranlib")
set(CMAKE_CXX_COMPILER "clang++")
set(CMAKE_CXX_COMPILER_AR "llvm-ar")
set(CMAKE_CXX_COMPILER_RANLIB "llvm-ranlib")
set(CMAKE_ASM_COMPILER "clang")
set(CMAKE_ASM_COMPILER_AR "llvm-ar")
set(CMAKE_ASM_COMPILER_RANLIB "llvm-ranlib")
set(CMAKE_C_COMPILER_TARGET ${triple})
set(CMAKE_CXX_COMPILER_TARGET ${triple})
set(CMAKE_ASM_COMPILER_TARGET ${triple})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

View File

@ -1,85 +0,0 @@
# Serene Programming Language
#
# Copyright (c) 2019-2024 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, version 2.
#
# 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/>.
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${LIBSERENE_INCLUDE_DIR})
add_subdirectory(lib/serene)
get_target_property(LIBNAME Serene::core CMAKE_PKG_NAME)
# Install rules for libserene target
install(TARGETS core
EXPORT CoreExports
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
# Install rules for the public header files.
install(DIRECTORY ${INCLUDE_DIR}/serene
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING
PATTERN *.h
PATTERN *.td
PATTERN "CMake*" EXCLUDE)
# Install rule for the public generated header files
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING
PATTERN *.h
PATTERN *.td
PATTERN *.h.inc
PATTERN "CMake*" EXCLUDE)
include(CMakePackageConfigHelpers)
# Package config file let us use find_package with serene
configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/${LIBNAME}Config.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/${LIBNAME}Config.cmake"
INSTALL_DESTINATION
${CMAKE_INSTALL_LIBDIR}/cmake/serene-core-${PROJECT_VERSION}
)
write_basic_package_version_file(
"CoreConfigVersion.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/${LIBNAME}Config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${LIBNAME}ConfigVersion.cmake"
DESTINATION
${CMAKE_INSTALL_LIBDIR}/cmake/serene-core-${PROJECT_VERSION}
)
# Install the package exports
install(EXPORT CoreExports
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/serene-core-${PROJECT_VERSION}
NAMESPACE serene::)
# Testing only available if this is the main app
# Emergency override SERENE_CMAKE_BUILD_TESTING provided as well
if(SERENE_BUILD_TESTING)
message("Build the test binary")
add_subdirectory(tests)
endif()

View File

@ -1,21 +0,0 @@
# Serene Programming Language
#
# Copyright (c) 2019-2024 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, version 2.
#
# 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_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Exports.cmake")
check_required_components("@PROJECT_NAME@")

View File

@ -1,70 +0,0 @@
# Serene Programming Language
#
# Copyright (c) 2019-2024 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, version 2.
#
# 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/>.
#TODO: To support MacOS look into cmake's public headers
# https://cmake.org/cmake/help/latest/prop_tgt/PUBLIC_HEADER.html
# Prevent any future RPATH issue on Posix
if(NOT APPLE)
set(CMAKE_INSTALL_RPATH $ORIGIN)
endif()
set(SOURCES core.cpp)
add_library(core OBJECT
${SOURCES})
#add_custom_target(serene.core)
# Create an ALIAS target. This way if we mess up the name
# there will be an cmake error inseat of a linker error which is harder
# to understand. So any binary that wants to use serene has to
# use `Serene::core` alias instead
add_library(Serene::core ALIAS core)
set_target_properties(core PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
CMAKE_PKG_NAME SereneCore
# Warn on unused libs
LINK_WHAT_YOU_USE TRUE
CXX_INCLUDE_WHAT_YOU_USE "${iwyu_path}"
C_INCLUDE_WHAT_YOU_USE "${iwyu_path}"
# LTO support we need the actual object file
# LTO will export them to llvm IR
INTERPROCEDURAL_OPTIMIZATION FALSE)
target_compile_options(core PRIVATE --static)
target_link_options(core PRIVATE --static)
if(SERENE_ENABLE_TIDY)
set_target_properties(core PROPERTIES CXX_CLANG_TIDY ${CLANG_TIDY_PATH})
endif()
if (CPP_20_SUPPORT)
target_compile_features(core PUBLIC cxx_std_20)
else()
target_compile_features(core PUBLIC cxx_std_17)
endif()
# We need this directory, and users of our library will need it too
target_include_directories(core PUBLIC "$<BUILD_INTERFACE:${INCLUDE_DIR}>")
target_include_directories(core PUBLIC "$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>")
# Generate the export.h
include(GenerateExportHeader)
generate_export_header(core EXPORT_FILE_NAME ${PROJECT_BINARY_DIR}/include/serene/core/export.h)
target_link_libraries(core PRIVATE)

View File

@ -1,20 +0,0 @@
/*
* Serene Programming Language
*
* Copyright (c) 2019-2024 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, version 2.
*
* 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/>.
*/
#include <compiler.cpp.inc>
#include <reader.cpp.inc>

154
dev.org
View File

@ -1,7 +1,7 @@
#+TITLE: Serene Development
#+AUTHOR: Sameer Rahmani
#+SEQ_TODO: TODO(t/!) NEXT(n/!) BLOCKED(b@/!) | DONE(d%) WONT_DO(c@/!) FAILED(f@/!)
#+TAGS: DOCS(d) EXAMPLES(e) serenecli(c) reader(r) context(x) Misc(m) JIT(j) GC(g) Tool(t)
#+TAGS: DOCS(d) EXAMPLES(e) serenecli(c) reader(r) context(x) Misc(m)
#+STARTUP: logdrawer logdone logreschedule indent content align constSI entitiespretty nolatexpreview
#+OPTIONS: tex:t
#+HTML_MATHJAX: align: left indent: 5em tagside: left font: Neo-Eule
@ -36,8 +36,6 @@ Then here is the list or parsers that we have considered
- [[http://www.lispworks.com/documentation/HyperSpec/Body/02_df.htm][Backquote in CL]]
- [[https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node367.html][Backquote spec in Common Lisp the Language, 2nd Edition]]
- [[http://christophe.rhodes.io/notes/blog/posts/2014/backquote_and_pretty_printing/][Backquote and pretty printing]]
*** Compilers
- https://bernsteinbear.com/blog/compiling-a-lisp-0/
** Rust
- [[https://doc.rust-lang.org/book/][The Rust book]] (in [[https://www.reddit.com/r/rust/comments/2s1zj2/the_rust_programming_language_book_as_epub/][EPUB]] format)
** LLVM
@ -57,13 +55,6 @@ Then here is the list or parsers that we have considered
- [[https://julialang.org/research/julia-fresh-approach-BEKS.pdf][Julia: A Fresh Approach toNumerical Computing]]
** Cranelift
- [[https://github.com/bytecodealliance/wasmtime/tree/master/cranelift][Source tree]]
** Type Systems
- [[https://www.cs.cmu.edu/~rwh/courses/hott/][Homotopy Type Theory]]
- No, dynamic type systems are not inherently more open:
https://lexi-lambda.github.io/blog/2020/01/19/no-dynamic-type-systems-are-not-inherently-more-open/
- Type theory resources:
https://github.com/jozefg/learn-tt
** Memory management
- [[https://deepu.tech/memory-management-in-golang/][Visualizing memory management in Golang]]
- [[http://goog-perftools.sourceforge.net/doc/tcmalloc.html][TCMalloc : Thread-Caching Malloc]]
@ -71,19 +62,12 @@ Then here is the list or parsers that we have considered
** Concurrency
- [[https://www.ardanlabs.com/blog/2018/08/scheduling-in-go-part1.html][Scheduling In Go (Series)]]
** Garbage collection :GC:
** Garbage collection
- [[https://v8.dev/blog/high-performance-cpp-gc][GC on V8]]
- [[https://www.microsoft.com/en-us/research/uploads/prod/2020/11/perceus-tr-v1.pdf][Perceus: Garbage Free Reference Counting with Reuse]]
*** [[https://www.hboehm.info/gc/][Boehm GC]] :Tool:
*** [[https://www.ravenbrook.com/project/mps/][MPS]] :Tool:
*** [[https://www.mmtk.io/code][MMTK]] :Tool:
*** [[https://github.com/JWesleySM/Whiro][Whiro]] :Tool:
This is not GC but a tool to debug GC and memory allocation.
- [[https://www.hboehm.info/gc/][Boehm GC]]
** JIT
- [[https://asmjit.com/][Machine code generator for C++]]
- https://www.youtube.com/watch?v=hILdR8XRvdQ&t=1511s
** Optimizations
- [[https://sunfishcode.github.io/blog/2018/10/22/Canonicalization.html][Canonicalization]]
@ -93,10 +77,6 @@ This is not GC but a tool to debug GC and memory allocation.
It would be cool to have macro to instruct the compiler about the likelyhood
of a branch in a conditional. Something similar to kernel's *likely* and *unlikely*
macros
*** How to learn compilers: LLVM Edition
https://lowlevelbits.org/how-to-learn-compilers-llvm-edition/
*** Pointers Are Complicated III, or: Pointer-integer casts exposed
https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html
*** Execution Instrumentation
The compiler should be able to embed some code in the program to collect data about
the different execution paths or function instrumentation and other useful data the
@ -116,83 +96,25 @@ on ADF
*** Emacs mode
- [[https://www.wilfred.me.uk/blog/2015/03/19/adding-a-new-language-to-emacs/][Adding A New Language to Emacs]]
- [[https://www.wilfred.me.uk/blog/2014/09/27/the-definitive-guide-to-syntax-highlighting/][The Definitive Guide To Syntax Highlighting]]
** Linker
- [[https://lwn.net/Articles/276782/][20 part linker essay]]
- [[https://lld.llvm.org/index.html][LLD Usage]]
** LLVM
- [[https://blog.yossarian.net/2021/07/19/LLVM-internals-part-1-bitcode-format][LLVM Internals]]
*** TableGen
- [[https://llvm.org/docs/TableGen/BackGuide.html#creating-a-new-backend][Create a backend]]
** Toolchain
- https://llvm.org/docs/BuildingADistribution.html
** Cross compilation
- https://blog.gibson.sh/2017/11/26/creating-portable-linux-binaries/#some-general-suggestions
A nice to read article on some of the common problems when linking statically
with none default libc or libc++
** Useful courses and resources
- https://www.cs.cornell.edu/courses/cs6120/2020fa/lesson/
- https://cs.lmu.edu/~ray/notes/languagedesignnotes/
* Considerations
** Hashmaps
*** DOS attack
- https://www.anchor.com.au/blog/2012/12/how-to-explain-hash-dos-to-your-parents-by-using-cats/
- https://en.wikipedia.org/wiki/Collision_attack
* Ideas
** Destructure types
Imagine a type that is a subset of a Coll, and when we
pass a Coll to its type constructor in destructs the input and
construct the type base on the data that it needs only and
leave the rest untouched
** Hot function optimization
it would be nice for the JIT to add instrumentation to the compiled
functions and detect hot functions similar to how javascript jits do it
and recompile those functions with more optimization passes
* Conversations
** Solutions to link other ~libc~ rather than the default
From my discassion with ~lhames~
#+BEGIN_QUOTE
I can think of a few approaches with different trade-offs:
- Link your whole JIT (including LLVM) against musl rather than the default -- JIT'd
code uses the desired libc, there's only one libc in the JIT'd process, but the
cost is high (perhaps prohibitive, depending on your constraints)
- JIT out-of-process -- JIT (including LLVM) uses default libc and is compiled only once,
executor links the (alternative) desired libc at compile time and must be compiled each
time that you want to change it -- JIT'd code uses the desired libc, there's only one libc
in the JIT'd process, but the config is involved (requires a cross-process setup)
- JIT in process, link desired libc via JIT -- Easy to set up, but now you've got two
libcs in the process. I've never tested that config. It might just work, it might
fail at link or runtime in weird ways.
#+END_QUOTE
* TODOs
** Strings
*** TODO How to concat to strings in a functional and immutable way?
Should we include an pointer to another string???
** TODO Create =Catch2= generators to be used in tests. Specially for the =reader= tests
** TODO Investigate possible implementanion for Internal Errors
- An option is to use llvm registry functionality like the one used in =clang-doc= instead of
=errorVariants= var.
** TODO In =SereneContext::getLatestJITDylib= function, make sure that the JITDylib is still valid
Make sure that the returning Dylib still exists in the JIT
by calling =jit->engine->getJITDylibByName(dylib_name);=
** TODO Provide the CLI arguments to pass the =createTargetMachine=.
We need a way to tweak the target machine object. It's better to provide cli tools
to do so.
** TODO Walk the module and register the symbols with the engine (lazy and nonlazy) :JIT:
** TODO Change the compilation layer to accept MLIR modules instead of LLVM IR :JIT:
This way we can fine tune MLIR's passes based on the JIT settings as well
** TODO Create a pass to rename functions to include the ns name
** TODO Use =const= where ever it makes sense
** TODO Create different pass pipeline for different compilation phases
* TODOs
** Bootstrap*
*** TODO Use =const= where ever it makes sense
*** TODO Create different pass pipeline for different compilation phases
So we can use them directly via command line, like -O1 for example
** TODO Investigate the huge size of serenec
*** TODO Investigate the huge size of serenec
So far it seems that the static linking and the lack of tree shaking is the issue
** DONE Add the support for =ns-paths= :serenecli:context:
*** DONE Add the support for =ns-paths= :serenecli:context:
CLOSED: [2021-09-25 Sat 19:22]
:LOGBOOK:
- State "DONE" from "TODO" [2021-09-25 Sat 19:22]
@ -206,39 +128,39 @@ in python.
- [ ] Add the support to *Namespace*.
- [ ] Add the cli argument to the =bin/serene.cpp=
** TODO Error handling
*** TODO Error handling
Create proper error handling for the internal infra
** TODO Replace =llvm::outs()= with debug statements
** TODO Move the generatable logic out of its files and remove them
** TODO Add a CLI option to get any extra pass
** TODO Add support for =sourcemgr= for input files
** TODO Language Spec :DOCS:
** TODO A proper List implementation
** TODO Vector implementation
** TODO Hashmap implementation
** TODO Meta data support
** TODO Docstring support :DOCS:
*** TODO Replace =llvm::outs()= with debug statements
*** TODO Move the generatable logic out of its files and remove them
*** TODO Add a CLI option to get any extra pass
*** TODO Add support for =sourcemgr= for input files
*** TODO Language Spec :DOCS:
*** TODO A proper List implementation
*** TODO Vector implementation
*** TODO Hashmap implementation
*** TODO Meta data support
*** TODO Docstring support :DOCS:
- [ ] For functions and macros
- [ ] For namespaces and projects
- [ ] API to interact with docstrings and helps
** TODO FFI interface
** TODO nREPL
** TODO Emacs mode :Misc:
** TODO Number implementation
** TODO String implementation
** TODO Enum implementation
** TODO Protocol
** TODO Struct implementation
** TODO Multi arity functions
** TODO QuasiQuotation
** TODO Linter :Misc:
** TODO Document generator :DOCS:Misc:
** TODO Spec like functionality
** TODO Laziness implementation
** TODO Investigate the Semantic Error tree and tracking
*** TODO FFI interface
*** TODO nREPL
*** TODO Emacs mode :Misc:
*** TODO Number implementation
*** TODO String implementation
*** TODO Enum implementation
*** TODO Protocol
*** TODO Struct implementation
*** TODO Multi arity functions
*** TODO QuasiQuotation
*** TODO Linter :Misc:
*** TODO Document generator :DOCS:Misc:
*** TODO Spec like functionality
*** TODO Laziness implementation
*** TODO Investigate the Semantic Error tree and tracking
Basically we should be able to create an error tree on semantic analysis
time and trace semantic errors on different layers and intensively.
Is it a good idea ?
** Standard libraries
*** TODO IO library
*** TODO Test library
*** Standard libraries
**** TODO IO library
**** TODO Test library

View File

@ -1,93 +0,0 @@
# Serene Programming Language
#
# Copyright (c) 2019-2024 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, version 2.
#
# 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/>.
if (SERENE_ENABLE_DEVTOOLS)
add_executable(slir-lsp-server slir-lsp-server.cpp)
add_executable(Serene::SLIR::LSP ALIAS slir-lsp-server)
set_target_properties(slir-lsp-server PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
# Warn on unused libs
LINK_WHAT_YOU_USE TRUE
# LTO support
INTERPROCEDURAL_OPTIMIZATION TRUE)
if(SERENE_ENABLE_TIDY)
set_target_properties(slir-lsp-server PROPERTIES CXX_CLANG_TIDY ${CLANG_TIDY_PATH})
endif()
if (CPP_20_SUPPORT)
target_compile_features(slir-lsp-server PRIVATE cxx_std_20)
else()
target_compile_features(slir-lsp-server PRIVATE cxx_std_17)
endif()
target_link_libraries(slir-lsp-server
PRIVATE
Serene::lib
MLIRLspServerLib
)
target_include_directories(slir-lsp-server PRIVATE ${PROJECT_BINARY_DIR})
target_include_directories(slir-lsp-server PRIVATE ${INCLUDE_DIR})
install(TARGETS slir-lsp-server
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
# ========
# slir-opt
# ========
add_executable(slir-opt slir-opt.cpp)
add_executable(Serene::SLIR::Opt ALIAS slir-opt)
set_target_properties(slir-opt PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
# Warn on unused libs
LINK_WHAT_YOU_USE TRUE
# LTO support
INTERPROCEDURAL_OPTIMIZATION TRUE)
if(SERENE_ENABLE_TIDY)
set_target_properties(slir-opt PROPERTIES CXX_CLANG_TIDY ${CLANG_TIDY_PATH})
endif()
if (CPP_20_SUPPORT)
target_compile_features(slir-opt PRIVATE cxx_std_20)
else()
target_compile_features(slir-opt PRIVATE cxx_std_17)
endif()
target_link_libraries(slir-opt
PRIVATE
Serene::lib
MLIROptLib
)
target_include_directories(slir-opt PRIVATE ${PROJECT_BINARY_DIR})
target_include_directories(slir-opt PRIVATE ${INCLUDE_DIR})
install(TARGETS slir-opt
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()

View File

@ -1,39 +0,0 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2024 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, version 2.
*
* 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/>.
*/
#include "serene/passes.h"
#include "serene/slir/dialect.h"
#include <mlir/Dialect/Arithmetic/IR/Arithmetic.h>
#include <mlir/Dialect/Func/IR/FuncOps.h>
#include <mlir/Dialect/LLVMIR/LLVMDialect.h>
#include <mlir/IR/Dialect.h>
#include <mlir/Tools/mlir-opt/MlirOptMain.h>
int main(int argc, char **argv) {
mlir::DialectRegistry registry;
serene::slir::registerTo(registry);
registry.insert<mlir::arith::ArithmeticDialect, mlir::func::FuncDialect,
mlir::LLVM::LLVMDialect>();
serene::passes::registerAllPasses();
return static_cast<int>(
mlir::failed(mlir::MlirOptMain(argc, argv, "slir-opt", registry)));
}

16
docs/CMakeLists.txt Normal file
View File

@ -0,0 +1,16 @@
set(DOXYGEN_GENERATE_HTML YES)
set(DOXYGEN_GENERATE_MAN YES)
set(DOXYGEN_EXTRACT_ALL YES)
set(DOXYGEN_BUILTIN_STL_SUPPORT YES)
set(DOXYGEN_PROJECT_BRIEF "Just another Lisp")
message("<<<<<<<<<<<<<<<<<<<<<<<<<<<")
message(${PROJECT_SOURCE_DIR})
message(${INCLUDE_DIR})
doxygen_add_docs(docs
#"${CMAKE_CURRENT_SOURCE_DIR}/index.md"
"${PROJECT_SOURCE_DIR}/src/"
${INCLUDE_DIR})
add_dependencies(serenec docs)

View File

@ -1,14 +0,0 @@
FROM docker.io/python
WORKDIR /app
COPY . .
RUN pip install -r docs/requirements.txt
RUN mkdocs build
FROM docker.io/busybox
COPY --from=0 /app/build/docs /app
WORKDIR /app
CMD ["busybox", "httpd", "-f", "-v", "-p", "3000"]

View File

@ -1,2 +1,4 @@
(def main (fn () 4))
(def main
(fn () 4))
(def main1 (fn (v y n) 3))

View File

@ -1,38 +0,0 @@
module @some.ns {
// Value operator ----
%0 = "serene.value"(){value= 3} : () -> i64
// compact form
%1 = serene.value 3 : i32
%x = serene.symbol "some.ns" "x"
// Def operator ----
%foo = "serene.define"(%0){sym_name = "foo"}: (i64) -> !serene.symbol
// compact form
%bar = serene.define "bar", %0 : i64
// Fn operator ----
%f1 = "serene.fn"()({
^entry(%fnarg1 : i1, %fnarg2 : !serene.symbol):
%2 = serene.value 3 : i32
// Def operator ----
%baz = "serene.define"(%fnarg1){sym_name = "baz"}: (i1) -> !serene.symbol
serene.ret %baz : !serene.symbol
},
{
^b1(%f1 : i1):
%3 = serene.value 4 : i32
// Def operator ----
%baz1 = "serene.define"(%3){sym_name = "baz"}: (i32) -> !serene.symbol
serene.ret %baz1 : !serene.symbol
^b2:
%baz2 = "serene.define"(%3){sym_name = "baz"}: (i32) -> !serene.symbol
serene.ret %baz2 : !serene.symbol
}){name = "some-fn", return_type = i32} : () -> !serene.fn
%a1 = serene.value 1 : i1
%a2 = serene.value "x" : !serene.symbol
%result = serene.call %f1(%a1, %a2){} : (i1, !serene.symbol) -> i32
}

View File

@ -1,80 +0,0 @@
---
title: Getting Started
---
# Getting Started
Serene is under heavy development. This guide is dedicated to help you to get started with
Serene development.
This guide assumes that you are familiar with C/C++ development and ecosystem.
## Are you a Linux user?
If you are using Linux (x86_64 only), then you're in luck. The `builder` script
will download the required toolchain automatically for you and set it up. So,
you can just use `builder` subcommands to develop serene (you still need to
install `cmake` and `ninja`).
You can disable this behaviour by setting the `USE_SERENE_TOOLCHAIN` env variable to
anything beside "true".
## Dependencies
Here is the list of dependencies that need to be present:
- `LLVM` (You can find the exact version in the `builder` script)
- `CMake` `>= 3.19`
- `Ninja`
- `include-what-you-use`
- `Valgrind` (Optional and only for development)
- `CCache` (If you want faster builds, specially with the LLVM)
- `Boehm GC` `v8.2.2`
make sure to build in statically with `-fPIC` flag.
- `zstd` (Only if you want to use prebuilt dependencies on Linux)
- Musl libc `v1.2.3` (It's not required but highly recommended)
- `libc++` (same version as LLVM abviously. It's not required but highly recommended)
- `compiler-rt` (same version as LLVM abviously. It's not required but highly recommended)
Serene build system uses Musl, libc++, and compiler-rt to generate a static binary.
You can use glibc, libgcc, and libstdc++ instead. But you might not be able to
cross compiler with Serene and also if anything happen to you, I might not be able
to help (I'll try for sure).
## Setup development environment
Before, you have to set up the necessary git hooks as follows:
```bash
./builder setup
```
## Build and installing dependencies (Other platforms)
Currently, the `builder` script does not support any platform beside GNU/Linux. So, you
need to build the dependencies yourself and make them available to the builder.
By the way, If you are interested, you can just hack the builder script and accommodate your
platform and contribute your changes to the project.
To build the dependencies in your platform, you can use the https://devheroes.codes/Serene/bootstrap-toolchain
repo as a reference or even modify it to support other platforms. Any contribution will be appreciated.
After all, it's just a cmake project. So, don't be afraid.
## How to build
To build for development (Debug mode) just use `./builder build` to setup the build system,
and build the project once, and then you can just use `./builder compile` to build the changed files
only.
Check out the `builder` script for more subcommands and details.
## How to debug
Since we're using the Boehm GC, to use a debugger, we need to turn off some of the signal
handlers that the debugger sets. To run the debugger (by default, lldb) with `serene`
just use the `lldb-run` subcommand of the builder script. In the debugger, after setting the
break point on the `main` function (`b main`) then use the following commands on:
```
process handle -p yes -s no -n no SIGPWR
process handle -p yes -s no -n no SIGXCPU
process handle -p yes -s no -n no SIGSEGV
```
## Cheatsheets
- [Modern C++ Cheatsheet](https://github.com/muqsitnawaz/modern-cpp-cheatsheet)
- [Modern CMake](https://cliutils.gitlab.io/modern-cmake/)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -1,29 +0,0 @@
---
hide:
- navigation
- toc
title: Home
---
# “What I cannot create, I do not understand”
-- Richard Feynman
## Serene is ...
A modern lisp, and it is to be born. It started out of the curiosity of the author and his journey
through computer science and mathematics. We are at the early stages of the development process
and there is a long way to go. If you're interested, contact us by joining our mailing list and
checkout the git repository. Furthermore, we document our progress in development via some video
tutorials and code walkthrough that can be a good guide for the developers who are eager to join
the team. You can find the videos on [my :fontawesome-brands-youtube:{ .youtube } YouTube channel](https://www.youtube.com/c/lxsameer).
## Announcements:
### * How to build a compiler with LLVM and MLIR
I have decided to make a video series as a guide and walk through the Serenes code base. This
way, anyone who is interested in Serene but never done language development will have an easier
time getting started with Serene. It will also serve as a historical documentary for some
decisions and implementations that we made throughout the development process. The video series
in accessible via my YouTube channel and How to build a compiler with LLVM and MLIR playlist.
Looking forward to your feedback. :smile:
Date: `2021-08-15`

View File

@ -1,18 +0,0 @@
window.MathJax = {
tex: {
inlineMath: [["\\(", "\\)"]],
displayMath: [["\\[", "\\]"]],
processEscapes: true,
processEnvironments: true
},
options: {
ignoreHtmlClass: ".*|",
processHtmlClass: "arithmatex"
}
};
document$.subscribe(() => {
MathJax.typesetPromise()
})

View File

@ -1,192 +0,0 @@
---
title: Resources
---
# Development Resource
## LLVM
- [Brief Overview of LLVM](https://www.infoworld.com/article/3247799/what-is-llvm-the-power-behind-swift-rust-clang-and-more.html)
- [A bit in depth details on LLVM](https://aosabook.org/en/llvm.html)
- [Official LLVM tutorial C++](https://llvm.org/docs/tutorial/)
- [Interactive C++ with Cling](https://blog.llvm.org/posts/2020-11-30-interactive-cpp-with-cling/)
- [My First LLVM Compiler](https://www.wilfred.me.uk/blog/2015/02/21/my-first-llvm-compiler/)
- [A Complete Guide to LLVM for Programming Language Creators](https://mukulrathi.co.uk/create-your-own-programming-language/llvm-ir-cpp-api-tutorial/)
- [LLVM Internals](https://blog.yossarian.net/2021/07/19/LLVM-internals-part-1-bitcode-format)
- [How to learn about compilers (LLVM Version)](https://lowlevelbits.org/how-to-learn-compilers-llvm-edition/)
### TableGen
- [Create a backend](https://llvm.org/docs/TableGen/BackGuide.html#creating-a-new-backend)
## Data Structures
- [Pure functional datastructures papaer](https://www.cs.cmu.edu/~rwh/theses/okasaki.pdf)
- [Dynamic typing: syntax and proof theory](https://reader.elsevier.com/reader/sd/pii/0167642394000042?token=CEFF5C5D1B03FD680762FC4889A14C0CA2BB28FE390EC51099984536E12AC358F3D28A5C25C274296ACBBC32E5AE23CD)
- [Representing Type Information in Dynamically Typed Languages](https://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.39.4394)
- [An empirical study on the impact of static typing on software maintainability](https://www.researchgate.net/publication/259634489_An_empirical_study_on_the_impact_of_static_typing_on_software_maintainability)
## Other languages
- [Julia: A Fresh Approach toNumerical Computing](https://julialang.org/research/julia-fresh-approach-BEKS.pdf)
## Memory management
- [Visualizing memory management in Golang](https://deepu.tech/memory-management-in-golang/)
- [TCMalloc : Thread-Caching Malloc](http://goog-perftools.sourceforge.net/doc/tcmalloc.html)
- [A visual guide to Go Memory Allocator from scratch (Golang)](https://medium.com/@ankur_anand/a-visual-guide-to-golang-memory-allocator-from-ground-up-e132258453ed)
## Concurrency
- [Scheduling In Go (Series)](https://www.ardanlabs.com/blog/2018/08/scheduling-in-go-part1.html)
## Garbage collection
- [GC on V8](https://v8.dev/blog/high-performance-cpp-gc)
- [Perceus: Garbage Free Reference Counting with Reuse](https://www.microsoft.com/en-us/research/uploads/prod/2020/11/perceus-tr-v1.pdf)
- [Boehm GC](https://www.hboehm.info/gc/)
- [MPS](https://www.ravenbrook.com/project/mps/)
- [MMTK](https://www.mmtk.io/code)
- [Whiro](https://github.com/JWesleySM/Whiro)<br/>
This is not GC but a tool to debug GC and memory allocation.
## JIT
- [Machine code generator for C++](https://asmjit.com/)
- [LLVM's Next Generation of JIT API](https://www.youtube.com/watch?v=hILdR8XRvdQ)
## Optimizations
- [Canonicalization](https://sunfishcode.github.io/blog/2018/10/22/Canonicalization.html)
## Compiler
- [Stack frame layout on x86-64](https://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64)
- [Pointers Are Complicated](https://www.ralfj.de/blog/2020/12/14/provenance.html)
- [Pointers Are Complicated III, or: Pointer-integer casts exposed](https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html)
- [A compiler writting journal](https://github.com/DoctorWkt/acwj)
## Linker
- [20 part linker essay](https://lwn.net/Articles/276782/)
- [LLD Usage](https://lld.llvm.org/index.html)
## Toolchain
- [Building LLVM Distribution](https://llvm.org/docs/BuildingADistribution.html)
## Cross compilation
- [Creating portable Linux binaries](https://blog.gibson.sh/2017/11/26/creating-portable-linux-binaries/#some-general-suggestions)<br/>
A nice to read article on some of the common problems when linking statically
with none default libc or libc++
## Lang
- Scheme
* [Chicken Scheme - Easy-to-use compiler and interpreter, with lots of libraries](https://call-cc.org)
* [Stalin - Brutally optimizing Scheme compiler, with lots of optimization flags](https://github.com/barak/stalin)
* [Crafting Interpreters](https://craftinginterpreters.com/contents.html)
## Emacs mode
- [Adding A New Language to Emacs](https://www.wilfred.me.uk/blog/2015/03/19/adding-a-new-language-to-emacs/)
- [The Definitive Guide To Syntax Highlighting](https://www.wilfred.me.uk/blog/2014/09/27/the-definitive-guide-to-syntax-highlighting/)
## Mathematics
- [CS410 course: Advance Functional Programming](https://github.com/pigworker/CS410-18)<br/>
If you need to learn Agda (We use it for the mathematics side of Serene, to proof certain features)
check out
- [Programming Language Foundations in Agda](https://plfa.github.io/)<br/>
This book is an introduction to programming language theory using the proof assistant Agda.
### Curry-Howard correspondence
- [The formulae-as-types notion of construction](https://www.dcc.fc.up.pt/~acm/howard2.pdf)
- [Propositions as Types](https://www.youtube.com/watch?v=IOiZatlZtGU)
### Type Theory
- [Homotopy Type Theory](https://www.cs.cmu.edu/~rwh/courses/hott/)
- [No, dynamic type systems are not inherently more open](https://lexi-lambda.github.io/blog/2020/01/19/no-dynamic-type-systems-are-not-inherently-more-open/)
- Practical Foundations of Programming Languages
+ [Online copy (2nd Edition Preview)](http://www.cs.cmu.edu/~rwh/pfpl/2nded.pdf)
+ [Dead-tree copy (2nd Edition)](https://www.amazon.com/Practical-Foundations-Programming-Languages-Robert/dp/1107150302)
- Types and Programming Languages
+ [Online supplements](http://www.cis.upenn.edu/~bcpierce/tapl/)
+ [Dead-tree copy](https://mitpress.mit.edu/books/types-and-programming-languages)
- Advanced Topics in Types and Programming Languages
+ [Online supplements](http://www.cis.upenn.edu/~bcpierce/attapl/)
+ [Dead-tree copy](http://www.amazon.com/exec/obidos/ASIN/0262162288/benjamcpierce)
- The Works of Per Martin-Löf:
+ [1972](https://github.com/michaelt/martin-lof/blob/master/pdfs/An-Intuitionistic-Theory-of-Types-1972.pdf?raw=true)
+ [1979](https://github.com/michaelt/martin-lof/blob/master/pdfs/Constructive-mathematics-and-computer-programming-1982.pdf?raw=true)
+ [1984](https://github.com/michaelt/martin-lof/blob/master/pdfs/Bibliopolis-Book-retypeset-1984.pdf?raw=true)
+ [The Complete Works of Per Martin-Löf](https://github.com/michaelt/martin-lof)
- [Programming In Martin-Löf's Type Theory](http://www.cse.chalmers.se/research/group/logic/book/book.pdf)
- The Works of John Reynolds
* [Types, Abstraction and Parametric Polymorphism](http://www.cse.chalmers.se/edu/year/2010/course/DAT140_Types/Reynolds_typesabpara.pdf) (Parametricity for
System F)
* [A Logic For Shared Mutable State](http://www.cs.cmu.edu/~jcr/seplogic.pdf)
* [Course notes on separation logic](http://www.cs.cmu.edu/afs/cs.cmu.edu/project/fox-19/member/jcr/www15818As2011/cs818A3-11.html)
* [Course notes on denotational semantics](http://www.cs.cmu.edu/~jcr/cs819-00.html)
- [The HoTT book](http://homotopytypetheory.org/book/)
- [Student's Notes on HoTT](https://github.com/RobertHarper/hott-notes)
- [Materials for the Schools and Workshops on UniMath](https://github.com/UniMath/Schools)
### Proof Theory
- Frank Pfenning's Lecture Notes
* [Introductory Course](http://www.cs.cmu.edu/~fp/courses/15317-f09/)
* [Linear Logic](http://www.cs.cmu.edu/~fp/courses/15816-s12/)
* [Modal Logic](http://www.cs.cmu.edu/~fp/courses/15816-s10/)
- [Proofs and Types](http://www.paultaylor.eu/stable/prot.pdf)
- [The Blind Spot: Lectures on Logic](http://www.ems-ph.org/books/book.php?proj_nr=136&srch=browse_authors%7CGirard%2C+Jean-Yves)
- [Mustard Watches: An Integrated Approach to Time and Food](http://girard.perso.math.cnrs.fr/mustard/page1.html)
### Category Theory
- Category Theory in Context
* [Online version](http://www.math.jhu.edu/~eriehl/context.pdf)
* [Dead-tree version](http://store.doverpublications.com/048680903x.html)
* [The author's post on the book](https://golem.ph.utexas.edu/category/2016/11/category_theory_in_context.html)
- Practical Foundations of Mathematics
* [HTML version](http://www.paultaylor.eu/~pt/prafm/)
* [Dead-tree version](https://www.amazon.com/gp/product/0521631076)
- [Category Theory](http://www.amazon.com/Category-Theory-Oxford-Logic-Guides/dp/0199237182/ref=sr_1_1?ie=UTF8&qid=1439348930&sr=8-1&keywords=awodey+category+theory)
- [Ed Morehouse's Category Theory Lecture Notes](https://emorehouse.wescreates.wesleyan.edu/research/notes/intro_categorical_semantics.pdf)
- Categorical Logic and Type Theory
* [Jacob's thesis, containing much of what went into the book](http://www.cs.ru.nl/B.Jacobs/PAPERS/PhD.ps)
* [A definitely not suspicious online copy](https://people.mpi-sws.org/~dreyer/courses/catlogic/jacobs.pdf)
* [Dead-tree copy](https://www.amazon.com/exec/obidos/ASIN/0444501703/qid%3D922441598/002-9790597-0750031)
- [Introduction to Higher-Order Categorical Logic](https://www.amazon.com/Introduction-Higher-Order-Categorical-Cambridge-Mathematics/dp/0521356539/ref=pd_sim_14_5?_encoding=UTF8&psc=1&refRID=V4H286NSZWK4MWDPV17R)
- [Sheaves in Geometry and Logic](https://www.amazon.com/Sheaves-Geometry-Logic-Introduction-Universitext/dp/0387977104)
### Others
- [Gunter's "Semantics of Programming Language"](http://www.amazon.com/Semantics-Programming-Languages-Structures-Foundations/dp/0262071436/ref=sr_1_1?ie=UTF8&qid=1439349219&sr=8-1&keywords=gunter+semantics+of+programming+languages)
- [Abramsky and Jung's "Domain Theory"](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.50.8851)
- [Realizability: An Introduction to Its Categorical Side](https://www.amazon.com/Realizability-Introduction-its-Categorical-Side/dp/0444550208)
- OPLSS:<br/>
The Oregon Programming Languages Summer School is a 2 week long
bootcamp on PLs held annually at the university of Oregon. It's a
wonderful event to attend but if you can't make it they record all
their lectures anyways! They're taught be a variety of lecturers
but they're all world class researchers.
* [2012](https://www.cs.uoregon.edu/research/summerschool/summer12/curriculum.html)
* [2013](https://www.cs.uoregon.edu/research/summerschool/summer13/curriculum.html)
* [2014](https://www.cs.uoregon.edu/research/summerschool/summer14/curriculum.html)
* [2015](https://www.cs.uoregon.edu/research/summerschool/summer15/curriculum.html)
* [2016](https://www.cs.uoregon.edu/research/summerschool/summer16/curriculum.php)
* [2017](https://www.cs.uoregon.edu/research/summerschool/summer17/topics.php)
* [2018](https://www.cs.uoregon.edu/research/summerschool/summer18/topics.php)

View File

@ -1,18 +0,0 @@
[data-md-color-scheme=slate] #what-i-cannot-create-i-do-not-understand {
color: white;
font-weight: 700;
margin-bottom: -20px;
}
[data-md-color-scheme=default] #what-i-cannot-create-i-do-not-understand {
color: #2f2f2f;
font-weight: 700;
margin-bottom: -20px;
}
.md-typeset .md-annotation__index > ::before {
content: attr(data-md-annotation-id);
}
.md-typeset :focus-within > .md-annotation__index > ::before {
transform: none;
}

View File

@ -1,4 +0,0 @@
mkdocs-material
mike
mkdocs-git-revision-date-localized-plugin
mkdocs-glightbox

View File

@ -1,48 +0,0 @@
version: "3.9"
services:
serene-docs:
image: serenelang/serene-docs
environment:
USER_UID: 1100
USER_GID: 1100
security_opt:
- no-new-privileges:true
networks:
- public_lb
volumes:
- /var/run/docker.sock:/var/run/docker.sock
deploy:
labels:
- "traefik.enable=true"
- "traefik.http.routers.serene-lang.rule=Host(`serene-lang.org`)"
- "traefik.http.routers.serene-lang.entrypoints=websecure"
- "traefik.http.routers.serene-lang.tls=true"
- "traefik.http.routers.serene-lang.tls.certresolver=default"
- "traefik.http.services.serene-lang-web.loadbalancer.server.port=3000"
- "traefik.http.services.serene-lang-web.loadbalancer.server.scheme=http"
- "traefik.http.routers.serene-lang.service=serene-lang-web"
- "traefik.docker.network=public_lb"
- "traefik.http.middlewares.serene-lang-ratelimit.ratelimit.average=50"
- "traefik.http.middlewares.serene-lang-ratelimit.ratelimit.burst=10"
- "traefik.http.routers.serene-lang.middlewares=serene-lang-ratelimit"
mode: replicated
replicas: 1
restart_policy:
condition: on-failure
max_attempts: 3
update_config:
parallelism: 1
delay: 5s
order: stop-first
logging:
options:
max-size: "10m"
max-file: "3"
networks:
public_lb:
external: true
name: public_lb

View File

@ -1,80 +0,0 @@
#+TITLE: Serene's Language Specification
#+AUTHOR: Sameer Rahmani
#+SEQ_TODO: TODO(t/!) | DONE(d%)
#+TAGS:
#+STARTUP: logdrawer logdone logreschedule indent content align constSI entitiespretty nolatexpreview
#+OPTIONS: tex:t
#+HTML_MATHJAX: align: left indent: 5em tagside: left font: Neo-Eule
# book style has to be remapped to koma scripts scrbook
#+LATEX_CLASS: book
#+LATEX_HEADER: \usepackage[english]{babel}
#+LATEX_CLASS_OPTIONS: [fontsize=11pt,paper=a5, pagesize=auto]
#+LATEX_HEADER: \KOMAoptions{fontsize=11pt}
#+LATEX_HEADER: \usepackage[utf8]{inputenc}
#+LATEX_HEADER: \usepackage{microtype}
#+LATEX_HEADER: \usepackage{pxfonts}
#+LATEX_HEADER: \usepackage{amsmath}
#+LATEX_HEADER: \usepackage{amssymb}
#+LATEX_HEADER: \usepackage{mathabx}
#+LATEX_HEADER: \usepackage{tcolorbox}
#+LATEX_HEADER: \setlength{\parskip}{1em}
#+LATEX_HEADER: \newtcolorbox{infobox}[2][]{colback=cyan!5!white,before skip=14pt,after skip=8pt,colframe=cyan!75!black,sharp corners,title={#2},#1}
#+LATEX_HEADER: \newcommand\tab[1][1cm]{\hspace*{#1}}
#+LATEX_HEADER: \let\oldsection\section
#+LATEX_HEADER: \newcommand\caution[1]{\textcolor{blue}{\textbf{#1}}}
#+LATEX_HEADER: \renewcommand\section{\pagebreak\oldsection}
#+LATEX_HEADER: \hypersetup{hidelinks}
#+LATEX_HEADER: \renewcommand{\contentsname}{Serene's Spec}
\clearpage\null\newpage
\chapter{Overview of Serene}
* Basic Types
* Special Forms
** ~def~:
~def~ has the following form:
#+BEGIN_SRC lisp
(def <NAME> <VALUE>)
#+END_SRC
- Defines a global binding
- Returns the name of the binding as a symbol
- ~<NAME>~ has to be a symbol
- If ~def~ is not a top level expression, it will create an ~undef~ global binding which
will be set to the ~<VALUE>~ when the execution flow reaches the ~def~ itself.
* Libraries
In terms of static and dynamic libraries, If the library is a Serene library
meaning that it is designed to only work with serene (we will see how in a bit), then
whatever namespaces that it contains will be added to the compiler and all those
namespaces will be map to the library (all the namespaces will point to the same JITDylib).
But if the library is a generic static or dynamic library a namespace with the same
name as the library minus the suffix will be added to the compiler, for example ~libssh.so~
will be mapped to ~libssh~ namespace.
** Static
** Dynamic
** Object
* Unsorted
** Eval
Evaluating any form using =eval= will add the form to the namespace containing the
=eval= expression.
* Glossary
- Symbol :: A Lisp Symbol. Just a symbol. A name that might be bound to a value
and evaluates to the value.
- IR Symbol :: The ~Symbol~ infrastructure essentially provides a non-SSA mechanism in which to refer to an
operation in IR symbolically with a name. On MLIR level they are different from *native symbols*
even though we use them to refer to *native symbols*. But they don't necessarily map to
*native symbols*.
- Native Sybol :: As the name suggests native symbols refer to native code symbols. Like those you find in an
object file.

View File

@ -5,21 +5,21 @@
* DONE Episode 1 - Introduction
** What is it all about?
- Create a programming lang
- Guide for contributors
- A LLVM/MLIR guide
- Create a programming lang
- Guide for contributors
- A LLVM/MLIR guide
** The Plan
- Git branches
- No live coding
- Feel free to contribute
- Git branches
- No live coding
- Feel free to contribute
** Serene and a bit of history
- Other Implementations
- Requirements
- C++ 14
- CMake
- Repository: https://devheroes.codes/Serene
- Website: lxsameer.com
Email: lxsameer@gnu.org
- Other Implementations
- Requirements
- C++ 14
- CMake
- Repository: https://devheroes.codes/Serene
- Website: lxsameer.com
Email: lxsameer@gnu.org
* DONE Episode 2 - Basic Setup
CLOSED: [2021-07-10 Sat 09:04]
** Installing Requirements
@ -230,41 +230,41 @@ the following code blocks. Both of those are distributed with the LLVM.
*** General syntax
#+BEGIN_SRC mlir
%result:2 = "somedialect.blah"(%x#2) { some.attribute = true, other_attribute = 3 }
: (!somedialect<"example_type">) -> (!somedialect<"foo_s">, i8)
loc(callsite("main" at "main.srn":10:8))
%result:2 = "somedialect.blah"(%x#2) { some.attribute = true, other_attribute = 3 }
: (!somedialect<"example_type">) -> (!somedialect<"foo_s">, i8)
loc(callsite("main" at "main.srn":10:8))
#+END_SRC
*** Blocks and Regions
#+BEGIN_SRC mlir
func @simple(i64, i1) -> i64 {
^bb0(%a: i64, %cond: i1): // Code dominated by ^bb0 may refer to %a
cond_br %cond, ^bb1, ^bb2
cond_br %cond, ^bb1, ^bb2
^bb1:
br ^bb3(%a: i64) // Branch passes %a as the argument
br ^bb3(%a: i64) // Branch passes %a as the argument
^bb2:
%b = addi %a, %a : i64
br ^bb3(%b: i64) // Branch passes %b as the argument
%b = addi %a, %a : i64
br ^bb3(%b: i64) // Branch passes %b as the argument
// ^bb3 receives an argument, named %c, from predecessors
// and passes it on to bb4 along with %a. %a is referenced
// directly from its defining operation and is not passed through
// an argument of ^bb3.
^bb3(%c: i64):
//br ^bb4(%c, %a : i64, i64)
"serene.ifop"(%c) ({ // if %a is in-scope in the containing region...
// then %a is in-scope here too.
%new_value = "another_op"(%c) : (i64) -> (i64)
//br ^bb4(%c, %a : i64, i64)
"serene.ifop"(%c) ({ // if %a is in-scope in the containing region...
// then %a is in-scope here too.
%new_value = "another_op"(%c) : (i64) -> (i64)
^someblock(%new_value):
%x = "some_other_op"() {value = 4 : i64} : () -> i64
^someblock(%new_value):
%x = "some_other_op"() {value = 4 : i64} : () -> i64
}) : (i64) -> (i64)
}) : (i64) -> (i64)
^bb4(%d : i64, %e : i64):
%0 = addi %d, %e : i64
return %0 : i64 // Return is also a terminator.
%0 = addi %d, %e : i64
return %0 : i64 // Return is also a terminator.
}
#+END_SRC
@ -277,15 +277,15 @@ Command line arguments to emir =slir=
Output:
#+BEGIN_SRC mlir
module @user {
%0 = "serene.fn"() ( {
%2 = "serene.value"() {value = 0 : i64} : () -> i64
return %2 : i64
}) {args = {}, name = "main", sym_visibility = "public"} : () -> i64
%0 = "serene.fn"() ( {
%2 = "serene.value"() {value = 0 : i64} : () -> i64
return %2 : i64
}) {args = {}, name = "main", sym_visibility = "public"} : () -> i64
%1 = "serene.fn"() ( {
%2 = "serene.value"() {value = 0 : i64} : () -> i64
return %2 : i64
}) {args = {n = i64, v = i64, y = i64}, name = "main1", sym_visibility = "public"} : () -> i64
%1 = "serene.fn"() ( {
%2 = "serene.value"() {value = 0 : i64} : () -> i64
return %2 : i64
}) {args = {n = i64, v = i64, y = i64}, name = "main1", sym_visibility = "public"} : () -> i64
}
#+END_SRC
@ -298,16 +298,16 @@ Command line arguments to emir =mlir=
Output:
#+BEGIN_SRC mlir
module @user {
module @user {
func @main() -> i64 {
%c3_i64 = constant 3 : i64
return %c3_i64 : i64
%c3_i64 = constant 3 : i64
return %c3_i64 : i64
}
func @main1(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 {
%c3_i64 = constant 3 : i64
return %c3_i64 : i64
}
%c3_i64 = constant 3 : i64
return %c3_i64 : i64
}
}
#+END_SRC
*** LIR
@ -318,16 +318,16 @@ Command line arguments to emir =lir=
Output:
#+BEGIN_SRC mlir
module @user {
module @user {
llvm.func @main() -> i64 {
%0 = llvm.mlir.constant(3 : i64) : i64
llvm.return %0 : i64
%0 = llvm.mlir.constant(3 : i64) : i64
llvm.return %0 : i64
}
llvm.func @main1(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 {
%0 = llvm.mlir.constant(3 : i64) : i64
llvm.return %0 : i64
}
%0 = llvm.mlir.constant(3 : i64) : i64
llvm.return %0 : i64
}
}
#+END_SRC
*** LLVMIR
@ -338,36 +338,36 @@ Command line arguments to emir =llvmir=
Output:
#+BEGIN_SRC llvm
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
declare i8* @malloc(i64 %0)
declare i8* @malloc(i64 %0)
declare void @free(i8* %0)
declare void @free(i8* %0)
define i64 @main() !dbg !3 {
define i64 @main() !dbg !3 {
ret i64 3, !dbg !7
}
}
define i64 @main1(i64 %0, i64 %1, i64 %2) !dbg !9 {
define i64 @main1(i64 %0, i64 %1, i64 %2) !dbg !9 {
ret i64 3, !dbg !10
}
}
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!2}
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!2}
!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "mlir", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
!1 = !DIFile(filename: "LLVMDialectModule", directory: "/")
!2 = !{i32 2, !"Debug Info Version", i32 3}
!3 = distinct !DISubprogram(name: "main", linkageName: "main", scope: null, file: !4, type: !5, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !6)
!4 = !DIFile(filename: "REPL", directory: "/home/lxsameer/src/serene/serene/build")
!5 = !DISubroutineType(types: !6)
!6 = !{}
!7 = !DILocation(line: 0, column: 10, scope: !8)
!8 = !DILexicalBlockFile(scope: !3, file: !4, discriminator: 0)
!9 = distinct !DISubprogram(name: "main1", linkageName: "main1", scope: null, file: !4, line: 1, type: !5, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !6)
!10 = !DILocation(line: 1, column: 11, scope: !11)
!11 = !DILexicalBlockFile(scope: !9, file: !4, discriminator: 0)
!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "mlir", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
!1 = !DIFile(filename: "LLVMDialectModule", directory: "/")
!2 = !{i32 2, !"Debug Info Version", i32 3}
!3 = distinct !DISubprogram(name: "main", linkageName: "main", scope: null, file: !4, type: !5, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !6)
!4 = !DIFile(filename: "REPL", directory: "/home/lxsameer/src/serene/serene/build")
!5 = !DISubroutineType(types: !6)
!6 = !{}
!7 = !DILocation(line: 0, column: 10, scope: !8)
!8 = !DILexicalBlockFile(scope: !3, file: !4, discriminator: 0)
!9 = distinct !DISubprogram(name: "main1", linkageName: "main1", scope: null, file: !4, line: 1, type: !5, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !6)
!10 = !DILocation(line: 1, column: 11, scope: !11)
!11 = !DILexicalBlockFile(scope: !9, file: !4, discriminator: 0)
#+END_SRC
** Resources
@ -562,8 +562,7 @@ and tries to =resolve= *undefined* symbols
** Let's look at some code
** Resources:
- [[https://lwn.net/Articles/276782/][20 part linker essay]]
* DONE Episode 13 - Source Managers
CLOSED: [2021-12-18 Sat 11:17]
* Episode 13 - Source Managers
** FAQ:
- What tools are you using?
@ -583,500 +582,3 @@ I didn't show it in action
- ...
- LLVM provides a =SourceMgr= class that we're not using it
* DONE Episode 14 - JIT Basics
CLOSED: [2022-01-05 Wed 17:37]
** Updates:
- Lost my data :_(
- Fixed some compatibility issues
- New video series on *How to build an editor with Emacs Lisp*
** What is Just In Time Compilation?
- Compiling at "runtime" (air quote)
Or it might be better to say, "on demand compilation"
- Usually in interpreters and Runtimes
#+NAME: ep-14-jit-1
#+BEGIN_SRC graphviz-dot :file /tmp/jit.svg :cmdline -Kdot -Tsvg
digraph {
graph [bgcolor=transparent]
node [color=gray80 shape="box"]
edge [color=gray80]
rankdir = "LR"
a[label="Some kind of input code"]
b[label="JIT"]
c[label="Some sort of target code"]
d[label="Execute the result"]
a -> b -> c -> d
}
#+END_SRC
#+RESULTS: ep-14-jit-1
[[file:/tmp/jit.svg]]
#+NAME: ep-14-jit-2
#+BEGIN_SRC graphviz-dot :file /tmp/jit-2.svg :cmdline -Kdot -Tsvg
digraph G {
graph [bgcolor=transparent]
node [color=gray80 shape="box"]
edge [color=gray80]
rankdir = "LR"
a[label="Source code"]
b[label="Parser"]
c[label="Semantic Analyzer"]
d[label="IR Generator"]
e[label="Pass Manager"]
f[label="Object Layer"]
g[label="Native Code"]
z[label="Preload Core libs"]
a -> b
b -> c {label="AST"}
c -> d
z -> f
subgraph cluster0 {
color=lightgrey;
d -> e -> f
label = "JIT Engine";
}
f -> g
g -> Store
g -> Execute
}
#+END_SRC
#+RESULTS: ep-14-jit-2
[[file:/tmp/jit-2.svg]]
- Trade off
Compilation speed vs Execution speed
*** JIT vs Typical interpreters
** Why to use JIT?
- Make the interpreter to run "faster" (air quote again)
- Speed up the compilation
Avoid generating the target code and generate some byte-code instead
and then use a JIT in runtime to execute the byte-code.
- Use runtime data to find optimization opportunities.
- Support more archs
- And many other reasons
** How we're going to use a JIT?
- We need a JIT engine to implement Lisp Macros
- Compile time vs Runtime
+ Abstraction
- A JIT engine to just compile Serene code
- Our compiler will be a fancy JIT engine
#+NAME: ep-14-jit-3
#+BEGIN_SRC graphviz-dot :file /tmp/jit-3.svg :cmdline -Kdot -Tsvg
digraph {
graph [bgcolor=transparent]
node [color=gray80 shape="box"]
edge [color=gray80]
rankdir = "LR"
a[label="Serene AST"]
b[label="For every node"]
c[label="is it a macro call?" shapp="diamond"]
d[label="Add it to JIT"]
e[label="Expand it (call it)"]
f[label="Generate target code"]
a -> b
subgraph cluster0 {
color=lightgrey;
b -> c
c -> d [label="NO"]
c -> e [label="YES"]
e -> b
d -> f
label = "JIT Engine";
}
f -> Store
f -> Execute
}
#+END_SRC
#+RESULTS: ep-14-jit-3
[[file:/tmp/jit-3.svg]]
** LLVM/MLIR and JIT
- 3 different approaches
- MLIR's JIT
- LLVM JITs
+ MCJIT (Deprecated)
+ LLJIT (Based on ORCv2)
+ LazyLLJIT (Based on LLJIT)
- Use LLVM's ORCv2 directly to create an engine
* DONE Episode 15 - LLVM ORC JIT
CLOSED: [2022-01-28 Fri 12:15]
** Uptades:
- Created a bare min JIT that:
- Eagrly compiles namespaces
- Reload namespacs
- I guess this the time to start the Serene's Spec
** What is ORCv2?
- On request compiler
- Replaces MCJIT
- ORCv2 docs and examples
- Kaleidoscope tutorial (not complete)
Before We can move to Serene's code we need to understand ORC first
** Terminology
*** Execution Session
A running JIT program. It contains the JITDylibs, error reporting mechanisms, and dispatches
the materializers.
*** JITAddress
It's just an address of a JITed code
*** JITDylib
Represents a JIT'd dynamic library.
This class aims to mimic the behavior of a shared object, but without requiring
the contained program representations to be compiled up-front. The JITDylib's
content is defined by adding MaterializationUnits, and contained MaterializationUnits
will typically rely on the JITDylib's links-against order to resolve external references.
JITDylibs cannot be moved or copied. Their address is stable, and useful as
a key in some JIT data structures.
*** MaterializationUnit
A =MaterializationUnit= represents a set of symbol definitions that can
be materialized as a group, or individually discarded (when
overriding definitions are encountered).
=MaterializationUnits= are used when providing lazy definitions of symbols to
JITDylibs. The JITDylib will call materialize when the address of a symbol
is requested via the lookup method. The =JITDylib= will call discard if a
stronger definition is added or already present.
MaterializationUnit stores in JITDylibs.
*** MaterializationResponsibility
Represents and tracks responsibility for materialization and mediates interactions between
=MaterializationUnits= and =JITDylibs=. It provides a way for Dylib to find out about the outcome
of the materialization.
*** Memory Manager
A class that manages how JIT engine should use memory, like allocations and deallocations.
=SectionMemoryManager= is a simple memory manager that is provided by ORC.
*** Layers
ORC based JIT engines are constructed from several layers. Each layer has a specific responsiblity
and passes the result of its operation to the next layer. E.g Compile Layer, Link layer and ....
*** Resource Tracker
The API to remove or transfer the ownership of JIT resources. Usually, a resource is a module.
*** ThreadSafeModule
A thread safe container for the LLVM module.
** ORC highlevel API
- ORC provides a Layer based design to that let us create our own JIT engine.
- It comes with two ready to use engines:
We will look at their implementaion later
+ LLJIT
+ LLLazyJIT
** Two major solutions to build a JIT
- Wrap LLJIT or LLLazyJIT
- Create your own JIT engine and the wrapper
** Resources
*** Docs
- https://www.llvm.org/docs/ORCv2.html
*** Examples
- https://github.com/llvm/llvm-project/tree/main/llvm/examples/HowToUseLLJIT
- https://github.com/llvm/llvm-project/tree/main/llvm/examples/OrcV2Examples/LLJITDumpObjects
- https://github.com/llvm/llvm-project/tree/main/llvm/examples/OrcV2Examples/LLJITWithInitializers
- https://github.com/llvm/llvm-project/tree/main/llvm/examples/OrcV2Examples/LLJITWithLazyReexports
*** Talks
- [[https://www.youtube.com/watch?v=i-inxFudrgI][ORCv2 -- LLVM JIT APIs Deep Dive]]
- [[https://www.youtube.com/watch?v=MOQG5vkh9J8][Updating ORC JIT for Concurrency]]
- [[https://www.youtube.com/watch?v=hILdR8XRvdQ][ORC -- LLVM's Next Generation of JIT API]]
* DONE Eposide 16 - ORC Layers
CLOSED: [2022-02-26 Sat 12:50]
** Updates:
*** Support for adding AST directly to the JIT
*** Minor change to SLIR (big changes are coming)
*** Started to unify the llvm::Errors with Serene errors
*** Tablegen backend for error classes
** The plan for today
- We had a brief look at LLJIT/LLLazyJIT
- Better understanding
To understand them better we need to understand other components first. Starting from *layers*.
- We'll have a look at how to define our own layers in the future episodes.
** What are Layers?
- Layers are the basic blocks of an engine
- They are composable (kinda)
- Each layer has it's own requirements and details
- Each layer holds a reference to it's downstream layer
#+NAME: ep-16-jit-1
#+BEGIN_SRC graphviz-dot :file /tmp/ep16-1.svg :cmdline -Kdot -Tsvg
digraph {
graph [bgcolor=transparent]
node [color=gray80 shape="box"]
edge [color=gray80]
rankdir = "LR"
a[label="Input Type A"]
b[label="Input Type B"]
c[label="Layer A"]
d[label="Layer B"]
e[label="Layer C"]
f[label="Layer D"]
g[label="Layer E"]
h[label="Target Code"]
a -> c
b -> d
subgraph cluster0 {
color=lightgrey;
c -> e
d -> e
e -> f
f -> g
label = "JIT Engine";
}
g -> h
}
#+END_SRC
#+RESULTS: ep-16-jit-1
[[file:/tmp/ep16-1.svg]]
** Kaleidoscope JIT
- Chapter 1
#+NAME: ep-16-jit-2
#+BEGIN_SRC graphviz-dot :file /tmp/ep16-2.svg :cmdline -Kdot -Tsvg
digraph {
graph [bgcolor=transparent]
node [color=gray80 shape="box"]
edge [color=gray80]
rankdir = "LR"
a[label="LLVM IR Module"]
b[label="Compiler Layer"]
c[label="Object Layer"]
d[label="Target Code"]
a -> b
subgraph cluster0 {
color=lightgrey;
b -> c
label = "Kaleidoscope JIT";
}
c -> d
}
#+END_SRC
#+RESULTS: ep-16-jit-2
[[file:/tmp/ep16-2.svg]]
- Chapter 2
#+NAME: ep-16-jit-3
#+BEGIN_SRC graphviz-dot :file /tmp/ep16-3.svg :cmdline -Kdot -Tsvg
digraph {
graph [bgcolor=transparent]
node [color=gray80 shape="box"]
edge [color=gray80]
rankdir = "LR"
a[label="LLVM IR Module"]
b[label="Compiler Layer"]
c[label="Object Layer"]
e[label="Target Code"]
d[label="Optimize layer"]
a -> d
subgraph cluster0 {
color=lightgrey;
d -> b
b -> c
label = "Kaleidoscope JIT";
}
c -> e
}
#+END_SRC
#+RESULTS: ep-16-jit-3
[[file:/tmp/ep16-3.svg]]
* DONE Episode 17 - Custom ORC Layers
CLOSED: [2022-03-28 Mon 14:00]
** Updates:
- Finished the basic compiler wiring
- Restructured the source tree
- Tweaked the build system mostly for install targets
- Refactoring, cleaning up the code and writing tests
** Quick overview an ORC based JIT engine
- JIT engines are made out of layers
- Engines have a hierarchy of layers
- Layers don't know about each other
- Layers wrap the program representation in a =MaterializationUnit=, which is
then stored in the =JITDylib=.
- =MaterializationUnits= are responsible for describing the definitions they provide,
and for unwrapping the program representation and passing it back to the layer when
compilation is required.
- When a =MaterializationUnit= hands a program representation back to the layer it comes
with an associated =MaterializationResponsibility= object. This object tracks the
definitions that must be materialized and provides a way to notify the =JITDylib= once
they are either successfully materialized or a failure occurs.
** In order to build a custom layer we need:
*** A custom materialization unit
Let's have a look at the =MaterializationUnit= class.
*** And the layer class itself
The layer classes are not special but conventionally the come with few functions
like: =add=, =emit= and =getInterface=.
* DONE Episode 18 - JIT Engine Part 1
CLOSED: [2022-03-29 Tue 19:56]
** =Halley= JIT Engine
- It's not the final implementation
- Wraps LLJIT and LLLazyJIT
- Uses object cache layer
- Supports ASTs and Namespaces
* DONE Episode 19 - JIT Engine Part 2
CLOSED: [2022-05-04 Wed 21:30]
** How Serene is different from other programming langs?
- Serene is just a JIT engine
- Compiletime vs Runtime
+ The borderline is not clear in case of Serene
The Big picture
#+NAME: ep-19-jit-1
#+BEGIN_SRC graphviz-dot :file /tmp/ep19-1.svg :cmdline -Kdot -Tsvg
digraph {
fontcolor="gray80"
graph [bgcolor=transparent]
node [color=gray80 shape="box", fontcolor="gray80"]
edge [color=gray80, fontcolor="gray80"]
input_ns[label="Input Namespace"]
ast[label="AST"]
vast[label="Valid AST"]
ir[label="LLVM IR"]
subgraph cluster_2 {
label="REPL"
color="gray80"
graph [bgcolor=transparent, fontcolor="gray80"]
node [color=gray80 shape="box", fontcolor="gray80"]
input_form[label="Input Form"]
result[label="Evaluation result"]
result -> input_form[label="Loop"]
}
subgraph cluster_0 {
label="JIT"
color="gray80"
graph [bgcolor=transparent, fontcolor="gray80"]
node [color=gray80 shape="box", fontcolor="gray80"]
execute[label="Execute native code"]
binary[label="Binary File"]
subgraph cluster_1 {
label="AddAst/Ns"
color="gray80"
graph [bgcolor=transparent, fontcolor="gray80"]
node [color=gray80 shape="box", fontcolor="gray80"]
vast -> ir [label="Compile (No optimization)"]
subgraph cluster_4 {
label="Macro Expansion"
color="gray80"
graph [bgcolor=transparent, fontcolor="gray80"]
node [color=gray80 shape="box", fontcolor="gray80"]
vast -> macros [label=" Find the macros"]
macros -> JITDylib [label=" look up the required\n Symbols in compiled code"]
JITDylib -> symbols [label=" lookup"]
}
wrapped_code[lable="Wrapped IR"]
ir -> wrapped_code[label= " Wrap top level Forms in \nfunctions/calls"]
wrapped_code -> native [label=" Compile (No optimization)"]
}
symbols -> execute [label="Execute the functions mapped to the symbols"]
execute -> vast
execute -> result [label=" Print"]
execute -> binary [label=" Dump"]
native -> execute [label="invoke"]
native -> JITDylib [label="Add"]
JITDylib -> Context [label="Store as part the namespace"]
}
subgraph cluster_3 {
label="CLI interface"
color="gray80"
graph [bgcolor=transparent, fontcolor="gray80"]
node [color=gray80 shape="box", fontcolor="gray80"]
input_ns -> file [label=" resolve to file"]
}
input_form -> ast [label=" read"]
file -> ast [label=" read"]
ast -> vast [label=" Semantic Analysis"]
}
#+END_SRC
#+RESULTS: ep-19-jit-1
[[file:/tmp/ep19-1.png]]
** Let's look at some code
* Episode 20 - Future Roadmap
** So Far
- We created a bare bone and minimal compiler
+ That is capable of just in time and ahead of time compilation
- We had an over of MLIR and pass management
- We didn't spend time on fundamentals
** Design change
- The current implementation is suitable for a static compiler
- We want to move toward a more dynamic compiler
** What's next?
- Part 2
- We're going to focus on some of the compiler fundamentals
- We will create simple utilities to help us in our journey
- Hopefully we will talk about type systems
- We're going to sharpen our skills on LLVM/MLIR
- I'm going to work on the new design

View File

@ -1,149 +0,0 @@
{
"nodes": {
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1715865404,
"narHash": "sha256-/GJvTdTpuDjNn84j82cU6bXztE0MSkdnTWClUCRub78=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "8dc45382d5206bd292f9c2768b8058a8fd8311d9",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"git-hooks": {
"inputs": {
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": "nixpkgs",
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1715870890,
"narHash": "sha256-nacSOeXtUEM77Gn0G4bTdEOeFIrkCBXiyyFZtdGwuH0=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "fa606cccd7b0ccebe2880051208e4a0f61bfc8c1",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"git-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1710765496,
"narHash": "sha256-p7ryWEeQfMwTB6E0wIUd5V2cFTgq+DRRBz2hYGnJZyA=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e367f7a1fb93137af22a3908f00b9a35e2d286a7",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1714640452,
"narHash": "sha256-QBx10+k6JWz6u7VsohfSw8g8hjdBZEf8CFzXH1/1Z94=",
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/50eb7ecf4cd0a5756d7275c8ba36790e5bd53e33.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/50eb7ecf4cd0a5756d7275c8ba36790e5bd53e33.tar.gz"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1710695816,
"narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "614b4613980a522ba49f0d194531beddbb7220d3",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-23.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1712525377,
"narHash": "sha256-TbfZDd8NN6gx7eU5XQWgF/ojnnkTvn7cPXWdY4PVTMU=",
"owner": "lxsameer",
"repo": "nixpkgs",
"rev": "c738ee8ad1c35383037c20fa13eaac17c8ae98c5",
"type": "github"
},
"original": {
"owner": "lxsameer",
"repo": "nixpkgs",
"rev": "c738ee8ad1c35383037c20fa13eaac17c8ae98c5",
"type": "github"
}
},
"root": {
"inputs": {
"flake-parts": "flake-parts",
"git-hooks": "git-hooks",
"nixpkgs": "nixpkgs_2"
}
}
},
"root": "root",
"version": 7
}

132
flake.nix
View File

@ -1,132 +0,0 @@
# Serene Programming Language
#
# Copyright (c) 2019-2024 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, version 2.
#
# 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/>.
{
description = "Serene programming language";
inputs.nixpkgs.url =
"github:lxsameer/nixpkgs/c738ee8ad1c35383037c20fa13eaac17c8ae98c5";
#inputs.nixpkgs.url = "/home/lxsameer/src/nixpkgs/";
inputs.git-hooks.url = "github:cachix/git-hooks.nix";
inputs.flake-parts.url = "github:hercules-ci/flake-parts";
outputs = { self, nixpkgs, git-hooks, flake-parts, ... }@inputs:
flake-parts.lib.mkFlake { inherit inputs; } {
systems = [ "aarch64-darwin" "riscv64-linux" "x86_64-linux" ];
flake = { };
perSystem = { config, self', inputs', system, pkgs, lib, ... }:
let
version = "1.0.0";
overlays = (lib.attrsets.attrValues (import ./nix/overlays.nix { }));
utils = import ./nix/utils.nix { inherit nixpkgs; };
hostPkgs = pkgs;
targetPkgs = utils.getPkgs system overlays;
# Create a stdenv based on LLVM
stdenv = targetPkgs.stdenvAdapters.overrideCC targetPkgs.stdenv
targetPkgs.llvmPackages_18.clangUseLLVM;
gc = targetPkgs.callPackage ./nix/boehmgc.nix { inherit stdenv; };
zlib' = targetPkgs.zlib-ng.overrideAttrs (old: {
cmakeFlags = [
"-DCMAKE_INSTALL_PREFIX=/"
"-DBUILD_SHARED_LIBS=OFF"
"-DINSTALL_UTILS=ON"
"-DZLIB_COMPAT=ON"
];
});
# By default llvm adds zlib to `propagatedBuildInputs` which means any
# package that uses llvm will indirectly depends on zlib. And since
# by default that zlib is built as a shared lib (since our packageset
# is not static), We can't statically link to it. So, we just replace
# that zlib with our override of zlib-ng
clang' = stdenv.cc.overrideAttrs (old: {
propagatedBuildInputs = [ stdenv.cc.bintools ]
++ [ targetPkgs.zlib.static ];
});
llvm = targetPkgs.llvmPackages_18.llvm.overrideAttrs
(old: { propagatedBuildInputs = [ targetPkgs.zlib.static ]; });
# This is the actual stdenv that we need to use anywhere else
stdenv' =
targetPkgs.stdenvAdapters.overrideCC targetPkgs.stdenv clang';
nativeBuildToolsDeps = (with hostPkgs; [ cmake ninja ccache ]);
buildToolsDeps = (with targetPkgs; [
llvm
llvmPackages_18.mlir
llvmPackages_18.clang
iwyu
]);
buildDeps = (with targetPkgs; [
gc
zlib'
llvm
llvmPackages_18.mlir
llvmPackages_18.clang
]);
testDeps = (with hostPkgs; [ gtest gmock gbenchmark ]);
in {
devShells.default =
(targetPkgs.mkShell.override { stdenv = stdenv'; }) {
inherit (self.checks.${system}.git-hook-check) shellHook;
nativeBuildInputs = nativeBuildToolsDeps ++ buildToolsDeps;
buildInputs = buildDeps ++ testDeps
++ self.checks.${system}.git-hook-check.enabledPackages;
};
packages.blah = buildDeps ++ testDeps ++ nativeBuildToolsDeps
++ buildToolsDeps;
packages.devshell = stdenv'.mkDerivation {
inherit version;
name = "devshell";
src = ./.;
doBuild = false;
doUnpack = false;
doCheck = false;
nativeBuildInputs = nativeBuildToolsDeps ++ buildToolsDeps;
buildInputs = buildDeps ++ testDeps;
};
checks = {
git-hook-check = git-hooks.lib.${system}.run {
src = ./.;
hooks = {
nixfmt.enable = true;
clang-format = {
enable = true;
types_or = hostPkgs.lib.mkForce [ "c" "c++" ];
};
shellcheck.enable = true;
cmake-format.enable = true;
};
};
};
};
};
}

1
include/CMakeLists.txt Normal file
View File

@ -0,0 +1 @@
add_subdirectory("serene/slir/")

View File

@ -0,0 +1,11 @@
#ifndef CONFIG_H
#define CONFIG_H
// the configured options and settings
#define SERENE_VERSION "@PROJECT_VERSION@"
// Should we build the support for MLIR CL OPTIONS?
#cmakedefine SERENE_WITH_MLIR_CL_OPTION
#endif

162
include/serene/context.h Normal file
View File

@ -0,0 +1,162 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_CONTEXT_H
#define SERENE_CONTEXT_H
#include "serene/diagnostics.h"
#include "serene/environment.h"
#include "serene/export.h"
#include "serene/namespace.h"
#include "serene/passes.h"
#include "serene/slir/dialect.h"
#include "serene/source_mgr.h"
#include <llvm/ADT/None.h>
#include <llvm/ADT/Optional.h>
#include <llvm/ADT/StringRef.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/Support/Host.h>
#include <mlir/Dialect/StandardOps/IR/Ops.h>
#include <mlir/IR/MLIRContext.h>
#include <mlir/Pass/PassManager.h>
#include <memory>
namespace serene {
namespace reader {
class LocationRange;
} // namespace reader
namespace exprs {
class Expression;
using Node = std::shared_ptr<Expression>;
} // namespace exprs
enum class CompilationPhase {
Parse,
Analysis,
SLIR,
MLIR, // Lowered slir to other dialects
LIR, // Lowered to the llvm ir dialect
IR, // Lowered to the LLVMIR itself
NoOptimization,
O1,
O2,
O3,
};
class SERENE_EXPORT SereneContext {
struct Options {
/// Whether to use colors for the output or not
bool withColors = true;
Options() = default;
};
public:
// --------------------------------------------------------------------------
// IMPORTANT:
// These two contextes have to be the very first members of the class in
// order to destroy last. DO NOT change the order or add anything before
// them
// --------------------------------------------------------------------------
llvm::LLVMContext llvmContext;
mlir::MLIRContext mlirContext;
mlir::PassManager pm;
std::unique_ptr<DiagnosticEngine> diagEngine;
/// The source manager is responsible for loading namespaces and practically
/// managing the source code in form of memory buffers.
SourceMgr sourceManager;
/// The set of options to change the compilers behaivoirs
Options opts;
std::string targetTriple;
/// Insert the given `ns` into the context. The Context object is
/// the owner of all the namespaces. The `ns` will overwrite any
/// namespace with the same name.
void insertNS(NSPtr &ns);
/// Sets the n ame of the current namespace in the context and return
/// a boolean indicating the status of this operation. The operation
/// will fail if the namespace does not exist in the namespace table.
bool setCurrentNS(llvm::StringRef ns_name);
/// Return the current namespace that is being processed at the moment
Namespace &getCurrentNS();
/// Lookup the namespace with the give name in the current context and
/// return a pointer to it or a `nullptr` in it doesn't exist.
Namespace *getNS(llvm::StringRef ns_name);
SereneContext()
: pm(&mlirContext), diagEngine(makeDiagnosticEngine(*this)),
targetPhase(CompilationPhase::NoOptimization) {
mlirContext.getOrLoadDialect<serene::slir::SereneDialect>();
mlirContext.getOrLoadDialect<mlir::StandardOpsDialect>();
// We need to create one empty namespace, so that the JIT can
// start it's operation.
auto ns = makeNamespace(*this, "serene.user", llvm::None);
// TODO: Get the crash report path dynamically from the cli
// pm.enableCrashReproducerGeneration("/home/lxsameer/mlir.mlir");
// TODO: Set the target triple with respect to the CLI args
targetTriple = llvm::sys::getDefaultTargetTriple();
};
/// Set the target compilation phase of the compiler. The compilation
/// phase dictates the behavior and the output type of the compiler.
void setOperationPhase(CompilationPhase phase);
CompilationPhase getTargetPhase() { return targetPhase; };
int getOptimizatioLevel();
MaybeNS readNamespace(const std::string &name);
MaybeNS readNamespace(const std::string &name, reader::LocationRange loc);
private:
CompilationPhase targetPhase;
// The namespace table. Every namespace that needs to be compiled has
// to register itself with the context and appear on this table.
// This table acts as a cache as well.
std::map<std::string, NSPtr> namespaces;
// Why string vs pointer? We might rewrite the namespace and
// holding a pointer means that it might point to the old version
std::string current_ns;
};
/// Creates a new context object. Contexts are used through out the compilation
/// process to store the state
SERENE_EXPORT std::unique_ptr<SereneContext> makeSereneContext();
/// Terminates the serene compiler process in a thread safe manner
SERENE_EXPORT void terminate(SereneContext &ctx, int exitCode);
} // namespace serene
#endif

View File

@ -0,0 +1,106 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_DIAGNOSTICS_H
#define SERENE_DIAGNOSTICS_H
#include "serene/errors/constants.h"
#include "serene/errors/error.h"
#include "serene/reader/location.h"
#include "serene/source_mgr.h"
#include <serene/export.h>
#include <llvm/ADT/StringRef.h>
#include <llvm/Support/raw_ostream.h>
#include <mlir/IR/Diagnostics.h>
#include <memory>
namespace serene {
class SereneContext;
class DiagnosticEngine;
class Diagnostic {
// TODO: Add support for llvm::SMFixIt
friend DiagnosticEngine;
enum Type {
Error,
// TODO: Add support for remarks and notes
Remark,
Note,
};
SereneContext &ctx;
reader::LocationRange loc;
std::string fn;
errors::ErrorVariant *err = nullptr;
Type type = Type::Error;
std::string message, lineContents;
std::string getPrefix(llvm::StringRef prefix = "");
public:
Diagnostic(SereneContext &ctx, reader::LocationRange loc,
errors::ErrorVariant *e, llvm::StringRef msg,
llvm::StringRef fn = "")
: ctx(ctx), loc(loc), fn(fn), err(e), message(msg){};
protected:
void print(llvm::raw_ostream &os, llvm::StringRef prefix = "");
void writeColorByType(llvm::raw_ostream &os, llvm::StringRef str);
};
class DiagnosticEngine {
SereneContext &ctx;
mlir::DiagnosticEngine &diagEngine;
Diagnostic toDiagnostic(reader::LocationRange loc, errors::ErrorVariant &e,
llvm::StringRef msg, llvm::StringRef fn = "");
void print(llvm::raw_ostream &os, Diagnostic &d);
public:
DiagnosticEngine(SereneContext &ctx);
void enqueueError(llvm::StringRef msg);
void emitSyntaxError(reader::LocationRange loc, errors::ErrorVariant &e,
llvm::StringRef msg = "");
void emit(const errors::ErrorPtr &err);
void emit(const errors::ErrorTree &errs);
/// Throw out an error with the given `msg` and terminate the execution
void panic(llvm::StringRef msg);
};
/// Create a new instance of the `DiagnosticEngine` from the give
/// `SereneContext`
std::unique_ptr<DiagnosticEngine> makeDiagnosticEngine(SereneContext &ctx);
/// Throw out an error with the given `msg` and terminate the execution.
SERENE_EXPORT void panic(SereneContext &ctx, llvm::StringRef msg);
/// Throw the give `ErrorTree` \p errs and terminate the execution.
SERENE_EXPORT void throwErrors(SereneContext &ctx, errors::ErrorTree &errs);
} // namespace serene
#endif

View File

@ -1,7 +1,7 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2024 Sameer Rahmani <lxsameer@gnu.org>
* Copyright (c) 2019-2021 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
@ -16,12 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ENVIRONMENT_H
#define ENVIRONMENT_H
#ifndef SERENE_ENVIRONMENT_H
#define SERENE_ENVIRONMENT_H
#include "utils.h"
#include "serene/llvm/patches.h"
#include <llvm/ADT/StringMap.h>
#include <llvm/ADT/DenseMap.h>
#include <mlir/Support/LogicalResult.h>
namespace serene {
@ -29,21 +29,20 @@ namespace serene {
/// This class represents a classic lisp environment (or scope) that holds the
/// bindings from type `K` to type `V`. For example an environment of symbols
/// to expressions would be `Environment<Symbol, Node>`
template <typename V>
template <typename K, typename V>
class Environment {
Environment<V> *parent;
Environment<K, V> *parent;
using StorageType = llvm::StringMap<V>;
// The actual bindings storage
StorageType pairs;
llvm::DenseMap<K, V> pairs;
public:
Environment() : parent(nullptr) {}
explicit Environment(Environment *parent) : parent(parent){};
Environment(Environment *parent) : parent(parent){};
/// Look up the given `key` in the environment and return it.
std::optional<V> lookup(llvm::StringRef key) {
llvm::Optional<V> lookup(K key) {
if (auto value = pairs.lookup(key)) {
return value;
}
@ -52,27 +51,15 @@ public:
return parent->lookup(key);
}
return std::nullopt;
return llvm::None;
};
/// Insert the given `key` with the given `value` into the storage. This
/// operation will shadow an aleady exist `key` in the parent environment
mlir::LogicalResult insert_symbol(llvm::StringRef key, V value) {
auto result = pairs.insert_or_assign(key, value);
UNUSED(result);
mlir::LogicalResult insert_symbol(K key, V value) {
pairs.insert(std::pair<K, V>(key, value));
return mlir::success();
};
inline typename StorageType::iterator begin() { return pairs.begin(); }
inline typename StorageType::iterator end() { return pairs.end(); }
inline typename StorageType::const_iterator begin() const {
return pairs.begin();
}
inline typename StorageType::const_iterator end() const {
return pairs.end();
}
};
} // namespace serene

View File

@ -1,7 +1,7 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2024 Sameer Rahmani <lxsameer@gnu.org>
* Copyright (c) 2019-2021 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
@ -16,11 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "serene/core/core.h"
#include "serene/types/types.h"
#ifndef SERENE_ERRORS_H
#define SERENE_ERRORS_H
namespace serene {
#include "serene/errors/errc.h"
#include "serene/errors/error.h"
int read() { return 0; };
} // namespace serene
#endif

View File

@ -0,0 +1,120 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_ERRORS_CONSTANTS_H
#define SERENE_ERRORS_CONSTANTS_H
#include <llvm/Support/FormatVariadic.h>
#include <map>
#include <string>
#include <utility>
namespace serene {
namespace errors {
/// This enum represent the expression type and **not** the value type.
enum class ErrType {
Syntax,
Semantic,
Compile,
};
enum ErrID {
E0000 = 0,
E0001,
E0002,
E0003,
E0004,
E0005,
E0006,
E0007,
E0008,
E0009,
E0010,
E0011,
E0012,
E0013,
};
struct ErrorVariant {
ErrID id;
std::string description;
std::string longDescription;
ErrorVariant(ErrID id, std::string desc, std::string longDesc)
: id(id), description(std::move(desc)),
longDescription(std::move(longDesc)){};
std::string getErrId() { return llvm::formatv("E{0:d}", id); };
};
static ErrorVariant
UnknownError(E0000, "Can't find any description for this error.", "");
static ErrorVariant
DefExpectSymbol(E0001, "The first argument to 'def' has to be a Symbol.",
"");
static ErrorVariant DefWrongNumberOfArgs(
E0002, "Wrong number of arguments is passed to the 'def' form.", "");
static ErrorVariant FnNoArgsList(E0003, "'fn' form requires an argument list.",
"");
static ErrorVariant FnArgsMustBeList(E0004, "'fn' arguments should be a list.",
"");
static ErrorVariant CantResolveSymbol(E0005, "Can't resolve the given name.",
"");
static ErrorVariant
DontKnowHowToCallNode(E0006, "Don't know how to call the given expression.",
"");
static ErrorVariant PassFailureError(E0007, "Pass Failure.", "");
static ErrorVariant NSLoadError(E0008, "Faild to find a namespace.", "");
static ErrorVariant
NSAddToSMError(E0009, "Faild to add the namespace to the source manager.",
"");
static ErrorVariant
EOFWhileScaningAList(E0010, "EOF reached before closing of list", "");
static ErrorVariant InvalidDigitForNumber(E0011, "Invalid digit for a number.",
"");
static ErrorVariant
TwoFloatPoints(E0012, "Two or more float point characters in a number", "");
static ErrorVariant
InvalidCharacterForSymbol(E0013, "Invalid character for a symbol", "");
static std::map<ErrID, ErrorVariant *> ErrDesc = {
{E0000, &UnknownError}, {E0001, &DefExpectSymbol},
{E0002, &DefWrongNumberOfArgs}, {E0003, &FnNoArgsList},
{E0004, &FnArgsMustBeList}, {E0005, &CantResolveSymbol},
{E0006, &DontKnowHowToCallNode}, {E0007, &PassFailureError},
{E0008, &NSLoadError}, {E0009, &NSAddToSMError},
{E0010, &EOFWhileScaningAList}, {E0011, &InvalidDigitForNumber},
{E0012, &TwoFloatPoints}, {E0013, &InvalidCharacterForSymbol}};
} // namespace errors
} // namespace serene
#endif

View File

@ -0,0 +1,77 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_ERRORS_ERRC_H
#define SERENE_ERRORS_ERRC_H
#include <llvm/Support/Errc.h>
namespace serene {
/// A collection of common error codes in Serene
enum class errc {
argument_list_too_long = int(std::errc::argument_list_too_long),
argument_out_of_domain = int(std::errc::argument_out_of_domain),
bad_address = int(std::errc::bad_address),
bad_file_descriptor = int(std::errc::bad_file_descriptor),
broken_pipe = int(std::errc::broken_pipe),
device_or_resource_busy = int(std::errc::device_or_resource_busy),
directory_not_empty = int(std::errc::directory_not_empty),
executable_format_error = int(std::errc::executable_format_error),
file_exists = int(std::errc::file_exists),
file_too_large = int(std::errc::file_too_large),
filename_too_long = int(std::errc::filename_too_long),
function_not_supported = int(std::errc::function_not_supported),
illegal_byte_sequence = int(std::errc::illegal_byte_sequence),
inappropriate_io_control_operation =
int(std::errc::inappropriate_io_control_operation),
interrupted = int(std::errc::interrupted),
invalid_argument = int(std::errc::invalid_argument),
invalid_seek = int(std::errc::invalid_seek),
io_error = int(std::errc::io_error),
is_a_directory = int(std::errc::is_a_directory),
no_child_process = int(std::errc::no_child_process),
no_lock_available = int(std::errc::no_lock_available),
no_space_on_device = int(std::errc::no_space_on_device),
no_such_device_or_address = int(std::errc::no_such_device_or_address),
no_such_device = int(std::errc::no_such_device),
no_such_file_or_directory = int(std::errc::no_such_file_or_directory),
no_such_process = int(std::errc::no_such_process),
not_a_directory = int(std::errc::not_a_directory),
not_enough_memory = int(std::errc::not_enough_memory),
not_supported = int(std::errc::not_supported),
operation_not_permitted = int(std::errc::operation_not_permitted),
permission_denied = int(std::errc::permission_denied),
read_only_file_system = int(std::errc::read_only_file_system),
resource_deadlock_would_occur = int(std::errc::resource_deadlock_would_occur),
resource_unavailable_try_again =
int(std::errc::resource_unavailable_try_again),
result_out_of_range = int(std::errc::result_out_of_range),
too_many_files_open_in_system = int(std::errc::too_many_files_open_in_system),
too_many_files_open = int(std::errc::too_many_files_open),
too_many_links = int(std::errc::too_many_links)
};
/// The **official way** to create `std::error_code` in context of Serene.
inline std::error_code make_error_code(errc E) {
return std::error_code(static_cast<int>(E), std::generic_category());
};
}; // namespace serene
#endif

View File

@ -0,0 +1,78 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_ERRORS_ERROR_H
#define SERENE_ERRORS_ERROR_H
#include "serene/errors/constants.h"
#include "serene/errors/traits.h"
#include "serene/reader/traits.h"
#include "serene/traits.h"
#include <llvm/ADT/Optional.h>
namespace serene::reader {
class LoccationRange;
} // namespace serene::reader
namespace serene::errors {
class Error;
using ErrorPtr = std::shared_ptr<errors::Error>;
// tree? Yupe, Errors can be stackable which makes a vector of them a tree
using ErrorTree = std::vector<ErrorPtr>;
using OptionalErrors = llvm::Optional<ErrorTree>;
/// This data structure represent the Lisp error. This type of expression
/// doesn't show up in the AST but the compiler might rewrite the AST
/// to contains error expressions
class Error
: public WithTrait<Error, IError, reader::ILocatable, serene::IDebuggable> {
reader::LocationRange location;
ErrorVariant *variant;
std::string message;
public:
Error(reader::LocationRange &loc, ErrorVariant &err, llvm::StringRef msg)
: location(loc), variant(&err), message(msg){};
Error(reader::LocationRange &loc, ErrorVariant &err)
: location(loc), variant(&err){};
std::string toString() const;
reader::LocationRange &where();
ErrorVariant *getVariant();
std::string &getMessage();
~Error() = default;
};
/// Creates a new Error in the give location \p loc, with the given
/// variant \p and an optional message \p msg and retuns a shared ptr
/// to the error. This is the official API to make errors.
ErrorPtr makeError(reader::LocationRange &loc, ErrorVariant &err,
llvm::StringRef msg = "msg");
/// Creates a new ErrorTree out of a new Error that creats from the input
/// argument and pass them to `makeError` function.
ErrorTree makeErrorTree(reader::LocationRange &loc, ErrorVariant &err,
llvm::StringRef msg = "msg");
}; // namespace serene::errors
#endif

View File

@ -0,0 +1,37 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_ERRORS_TRAITS_H
#define SERENE_ERRORS_TRAITS_H
#include "serene/errors/constants.h"
#include "serene/traits.h"
namespace serene::errors {
template <typename ConcreteType>
class IError : public TraitBase<ConcreteType, IError> {
public:
IError(){};
IError(const IError &) = delete;
ErrorVariant *getVariant();
std::string getMessage();
};
} // namespace serene::errors
#endif

View File

@ -0,0 +1,74 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_EXPRS_CALL_H
#define SERENE_EXPRS_CALL_H
#include "serene/context.h"
#include "serene/errors/error.h"
#include "serene/exprs/expression.h"
#include "serene/exprs/list.h"
#include <llvm/ADT/StringRef.h>
#include <llvm/Support/Error.h>
#include <memory>
#include <string>
namespace serene {
namespace exprs {
class List;
/// This data structure represents a function. with a collection of
/// arguments and the ast of a body
class Call : public Expression {
public:
Node target;
Ast params;
Call(reader::LocationRange &loc, Node &target, Ast &params)
: Expression(loc), target(target), params(params){};
Call(Call &) = delete;
ExprType getType() const override;
std::string toString() const override;
MaybeNode analyze(SereneContext & /*ctx*/) override;
void generateIR(serene::Namespace & /*ns*/,
mlir::ModuleOp & /*m*/) override{};
static bool classof(const Expression *e);
/// Creates a call node out of a list.
/// For exmaple: `(somefn (param1 param2) param3)`. This function
/// is supposed to be used in the semantic analysis phase.
///
/// \param ctx The semantic analysis context object.
/// \param list the list in question.
static MaybeNode make(SereneContext &ctx, List *list);
~Call() = default;
};
} // namespace exprs
} // namespace serene
#endif

View File

@ -0,0 +1,71 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_EXPRS_DEF_H
#define SERENE_EXPRS_DEF_H
#include "serene/context.h"
#include "serene/errors/error.h"
#include "serene/exprs/expression.h"
#include <llvm/ADT/StringRef.h>
#include <llvm/Support/Error.h>
#include <memory>
#include <string>
namespace serene {
namespace exprs {
class List;
/// This data structure represents the operation to define a new binding via
/// the `def` special form.
class Def : public Expression {
public:
std::string binding;
Node value;
Def(reader::LocationRange &loc, llvm::StringRef binding, Node &v)
: Expression(loc), binding(binding), value(v){};
Def(Def &d) = delete;
ExprType getType() const override;
std::string toString() const override;
MaybeNode analyze(SereneContext & /*ctx*/) override;
void generateIR(serene::Namespace & /*ns*/, mlir::ModuleOp & /*m*/) override;
static bool classof(const Expression *e);
/// Create a Def node out a list. The list should contain the
/// correct `def` form like `(def blah value)`. This function
/// is supposed to be used in the semantic analysis phase.
///
/// \param ctx The semantic analysis context object.
/// \param list the list containing the `def` form
static MaybeNode make(SereneContext &ctx, List *list);
~Def() = default;
};
} // namespace exprs
} // namespace serene
#endif

View File

@ -0,0 +1,154 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_EXPRS_EXPRESSION_H
#define SERENE_EXPRS_EXPRESSION_H
#include "serene/context.h"
#include "serene/errors/error.h"
#include "serene/exprs/traits.h"
#include "serene/reader/location.h"
#include "serene/utils.h"
#include <mlir/IR/BuiltinOps.h>
#include <memory>
namespace serene {
/// Contains all the builtin AST expressions including those which do not appear
/// in the syntax directly. Like function definitions.
namespace exprs {
class Expression;
using Node = std::shared_ptr<Expression>;
using MaybeNode = Result<Node, errors::ErrorTree>;
using Ast = std::vector<Node>;
using MaybeAst = Result<Ast, errors::ErrorTree>;
static auto EmptyNode = MaybeNode::success(nullptr);
/// The base class of the expressions which provides the common interface for
/// the expressions to implement.
class Expression {
public:
/// The location range provide information regarding to where in the input
/// string the current expression is used.
reader::LocationRange location;
Expression(const reader::LocationRange &loc) : location(loc){};
virtual ~Expression() = default;
/// Returns the type of the expression. We need this funciton to perform
/// dynamic casting of expression object to implementations such as lisp or
/// symbol.
virtual ExprType getType() const = 0;
/// The AST representation of an expression
virtual std::string toString() const = 0;
/// Analyzes the semantics of current node and return a new node in case
/// that we need to semantically rewrite the current node and replace it with
/// another node. For example to change from a List containing `(def a b)`
/// to a `Def` node that represents defining a new binding.
///
/// \param ctx is the context object of the semantic analyzer.
virtual MaybeNode analyze(SereneContext &ctx) = 0;
/// Genenates the correspondig SLIR of the expressoin and attach it to the
/// given module.
///
/// \param ns The namespace that current expression is in it.
/// \param m The target MLIR moduleOp to attach the operations to
virtual void generateIR(serene::Namespace &ns, mlir::ModuleOp &m) = 0;
};
/// Create a new `node` of type `T` and forwards any given parameter
/// to the constructor of type `T`. This is the **official way** to create
/// a new `Expression`. Here is an example:
/// \code
/// auto list = make<List>();
/// \endcode
///
/// \param[args] Any argument with any type passed to this function will be
/// passed to the constructor of type T.
/// \return A unique pointer to an Expression
template <typename T, typename... Args>
Node make(Args &&...args) {
return std::make_shared<T>(std::forward<Args>(args)...);
};
/// Create a new `node` of type `T` and forwards any given parameter
/// to the constructor of type `T`. This is the **official way** to create
/// a new `Expression`. Here is an example:
/// \code
/// auto list = makeAndCast<List>();
/// \endcode
///
/// \param[args] Any argument with any type passed to this function will be
/// passed to the constructor of type T.
/// \return A unique pointer to a value of type T.
template <typename T, typename... Args>
std::shared_ptr<T> makeAndCast(Args &&...args) {
return std::make_shared<T>(std::forward<Args>(args)...);
};
/// The helper function to create a new `Node` and use that as the success case
// of a `Result`. It should be useds where every we want to return a `MaybeNode`
/// successfully
template <typename T, typename... Args>
Result<Node, errors::ErrorTree> makeSuccessfulNode(Args &&...args) {
return Result<Node, errors::ErrorTree>::success(
make<T>(std::forward<Args>(args)...));
};
/// The hlper function to create an Errorful `Result<T,...>` (`T` would be
/// either `Node` or `Ast` most of the time) with just one error created from
/// passing any argument to this function to the `serene::errors::Error`
/// constructor.
template <typename T, typename... Args>
Result<T, errors::ErrorTree> makeErrorful(Args &&...args) {
std::vector<errors::ErrorPtr> v{
std::move(makeAndCast<errors::Error>(std::forward<Args>(args)...))};
return Result<T, errors::ErrorTree>::error(v);
};
/// The hlper function to create an Error node (The failure case of a MaybeNod)
/// with just one error created from passing any argument to this function to
/// the `serene::errors::Error` constructor.
template <typename... Args>
MaybeNode makeErrorNode(Args &&...args) {
std::vector<errors::ErrorPtr> v{
std::move(makeAndCast<errors::Error>(std::forward<Args>(args)...))};
return MaybeNode::error(v);
};
/// Convert the given AST to string by calling the `toString` method
/// of each node.
SERENE_EXPORT std::string astToString(const Ast *);
/// Converts the given ExprType to string.
std::string stringifyExprType(ExprType);
/// Converts the given AST to string and prints it out
void dump(Ast &);
} // namespace exprs
} // namespace serene
#endif

77
include/serene/exprs/fn.h Normal file
View File

@ -0,0 +1,77 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_EXPRS_FN_H
#define SERENE_EXPRS_FN_H
#include "serene/context.h"
#include "serene/errors/error.h"
#include "serene/exprs/expression.h"
#include "serene/exprs/list.h"
#include "serene/namespace.h"
#include <llvm/ADT/StringRef.h>
#include <llvm/Support/Error.h>
#include <memory>
#include <string>
namespace serene {
namespace exprs {
class List;
/// This data structure represents a function. with a collection of
/// arguments and the ast of a body
class Fn : public Expression {
public:
std::string name;
// TODO: Use a coll type instead of a list here
List args;
Ast body;
Fn(SereneContext &ctx, reader::LocationRange &loc, List &args, Ast body);
Fn(Fn &f) = delete;
ExprType getType() const override;
std::string toString() const override;
MaybeNode analyze(SereneContext & /*ctx*/) override;
void generateIR(serene::Namespace & /*ns*/, mlir::ModuleOp & /*m*/) override;
static bool classof(const Expression *e);
/// Creates a function node out of a function definition
/// in a list. the list has to contain the correct definition
/// of a function, for exmaple: `(fn (args1 arg2) body)`.This function
/// is supposed to be used in the semantic analysis phase.
///
/// \param ctx The semantic analysis context object.
/// \param list the list containing the `fn` form
static MaybeNode make(SereneContext &ctx, List *list);
void setName(std::string);
~Fn() = default;
};
} // namespace exprs
} // namespace serene
#endif

View File

@ -0,0 +1,87 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_EXPRS_LIST_H
#define SERENE_EXPRS_LIST_H
#include "serene/context.h"
#include "serene/exprs/expression.h"
#include <llvm/ADT/Optional.h>
#include <string>
namespace serene {
namespace exprs {
/// This class represents a List in the AST level and not the List as the data
/// type.
class List : public Expression {
public:
// Internal elements of the lest (small vector of shared pointers to
// expressions)
Ast elements;
List(const List &l); // Copy ctor
List(List &&e) noexcept = default; // Move ctor
List(const reader::LocationRange &loc) : Expression(loc){};
List(const reader::LocationRange &loc, Node &e);
List(const reader::LocationRange &loc, Ast elems);
ExprType getType() const override;
std::string toString() const override;
void append(Node);
size_t count() const;
Ast from(uint index);
llvm::Optional<Expression *> at(uint index);
/// Return an iterator to be used with the `for` loop. It's implicitly called
/// by the for loop.
std::vector<Node>::const_iterator cbegin();
/// Return an iterator to be used with the `for` loop. It's implicitly called
/// by the for loop.
std::vector<Node>::const_iterator cend();
/// Return an iterator to be used with the `for` loop. It's implicitly called
/// by the for loop.
std::vector<Node>::iterator begin();
/// Return an iterator to be used with the `for` loop. It's implicitly called
/// by the for loop.
std::vector<Node>::iterator end();
MaybeNode analyze(SereneContext &ctx) override;
// NOLINTNEXTLINE(readability-named-parameter)
void generateIR(serene::Namespace &, mlir::ModuleOp &) override{};
~List() = default;
static bool classof(const Expression *e);
};
} // namespace exprs
} // namespace serene
#endif

View File

@ -0,0 +1,64 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_EXPRS_NUMBER_H
#define SERENE_EXPRS_NUMBER_H
#include "serene/context.h"
#include "serene/exprs/expression.h"
#include "serene/namespace.h"
#include <llvm/Support/FormatVariadic.h>
namespace serene {
namespace exprs {
/// This data structure represent a number. I handles float points, integers,
/// positive and negative numbers. This is not a data type representative.
/// So it won't cast to actual numeric types and it has a string container
/// to hold the parsed value.
struct Number : public Expression {
// TODO: Use a variant here instead to store different number types
std::string value;
bool isNeg;
bool isFloat;
Number(reader::LocationRange &loc, const std::string &num, bool isNeg,
bool isFloat)
: Expression(loc), value(num), isNeg(isNeg), isFloat(isFloat){};
ExprType getType() const override;
std::string toString() const override;
MaybeNode analyze(SereneContext &ctx) override;
void generateIR(serene::Namespace & /*ns*/, mlir::ModuleOp & /*m*/) override;
// TODO: This is horrible, we need to fix it after the mvp
int toI64() const;
~Number() = default;
static bool classof(const Expression *e);
};
} // namespace exprs
} // namespace serene
#endif

View File

@ -0,0 +1,60 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_EXPRS_SYMBOL_H
#define SERENE_EXPRS_SYMBOL_H
#include "serene/context.h"
#include "serene/exprs/expression.h"
#include <llvm/ADT/StringRef.h>
#include <string>
namespace serene {
namespace exprs {
/// This data structure represent the Lisp symbol. Just a symbol
/// in the context of the AST and nothing else.
class Symbol : public Expression {
public:
std::string name;
Symbol(reader::LocationRange &loc, llvm::StringRef name)
: Expression(loc), name(name){};
Symbol(Symbol &s) : Expression(s.location) { this->name = s.name; }
ExprType getType() const override;
std::string toString() const override;
MaybeNode analyze(SereneContext & /*ctx*/) override;
void generateIR(serene::Namespace & /*ns*/,
mlir::ModuleOp & /*m*/) override{};
~Symbol() = default;
static bool classof(const Expression *e);
};
} // namespace exprs
} // namespace serene
#endif

View File

@ -0,0 +1,47 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_EXPRS_TRAITS_H
#define SERENE_EXPRS_TRAITS_H
#include "serene/context.h"
#include "serene/reader/location.h"
#include "serene/reader/traits.h"
#include "serene/traits.h"
#include "serene/utils.h"
namespace serene::exprs {
/// This enum represent the expression type and **not** the value type.
enum class ExprType {
Symbol,
List,
Number,
Def,
Error,
Fn,
Call,
};
/// The string represantion of built in expr types (NOT DATATYPES).
static const char *exprTypes[] = {
"Symbol", "List", "Number", "Def", "Error", "Fn", "Call",
};
}; // namespace serene::exprs
#endif

173
include/serene/jit.h Normal file
View File

@ -0,0 +1,173 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
/**
* Commentary:
*/
#ifndef SERENE_JIT_H
#define SERENE_JIT_H
#include "serene/errors.h"
#include "serene/export.h"
#include "serene/exprs/expression.h"
#include "serene/namespace.h"
#include "serene/slir/generatable.h"
#include "serene/utils.h"
#include <llvm/ADT/StringRef.h>
#include <llvm/ExecutionEngine/JITEventListener.h>
#include <llvm/ExecutionEngine/ObjectCache.h>
#include <llvm/ExecutionEngine/Orc/LLJIT.h>
#include <llvm/Support/CodeGen.h>
#include <llvm/Support/Debug.h>
#include <mlir/Support/LLVM.h>
#include <memory>
#define JIT_LOG(...) \
DEBUG_WITH_TYPE("JIT", llvm::dbgs() << "[JIT]: " << __VA_ARGS__ << "\n");
namespace serene {
class SERENE_EXPORT JIT;
using MaybeJIT = llvm::Optional<std::unique_ptr<JIT>>;
/// A simple object cache following Lang's LLJITWithObjectCache example and
/// MLIR's SimpelObjectCache.
class ObjectCache : public llvm::ObjectCache {
public:
/// Cache the given `objBuffer` for the given module `m`. The buffer contains
/// the combiled objects of the module
void notifyObjectCompiled(const llvm::Module *m,
llvm::MemoryBufferRef objBuffer) override;
// Lookup the cache for the given module `m` or returen a nullptr.
std::unique_ptr<llvm::MemoryBuffer> getObject(const llvm::Module *m) override;
/// Dump cached object to output file `filename`.
void dumpToObjectFile(llvm::StringRef filename);
private:
llvm::StringMap<std::unique_ptr<llvm::MemoryBuffer>> cachedObjects;
};
class JIT {
// TODO: Should the JIT own the context ???
Namespace &ns;
std::unique_ptr<llvm::orc::LLJIT> engine;
std::unique_ptr<ObjectCache> cache;
/// GDB notification listener.
llvm::JITEventListener *gdbListener;
/// Perf notification listener.
llvm::JITEventListener *perfListener;
public:
JIT(Namespace &ns, bool enableObjectCache = true,
bool enableGDBNotificationListener = true,
bool enablePerfNotificationListener = true);
static MaybeJIT
make(Namespace &ns, mlir::ArrayRef<llvm::StringRef> sharedLibPaths = {},
mlir::Optional<llvm::CodeGenOpt::Level> jitCodeGenOptLevel = llvm::None,
bool enableObjectCache = true, bool enableGDBNotificationListener = true,
bool enablePerfNotificationListener = true);
/// Looks up a packed-argument function with the given name and returns a
/// pointer to it. Propagates errors in case of failure.
llvm::Expected<void (*)(void **)> lookup(llvm::StringRef name) const;
/// Invokes the function with the given name passing it the list of opaque
/// pointers to the actual arguments.
llvm::Error
invokePacked(llvm::StringRef name,
llvm::MutableArrayRef<void *> args = llvm::None) const;
/// Trait that defines how a given type is passed to the JIT code. This
/// defaults to passing the address but can be specialized.
template <typename T>
struct Argument {
static void pack(llvm::SmallVectorImpl<void *> &args, T &val) {
args.push_back(&val);
}
};
/// Tag to wrap an output parameter when invoking a jitted function.
template <typename T>
struct FnResult {
FnResult(T &result) : value(result) {}
T &value;
};
/// Helper function to wrap an output operand when using
/// ExecutionEngine::invoke.
template <typename T>
static FnResult<T> result(T &t) {
return FnResult<T>(t);
}
// Specialization for output parameter: their address is forwarded directly to
// the native code.
template <typename T>
struct Argument<Result<T>> {
static void pack(llvm::SmallVectorImpl<void *> &args, FnResult<T> &result) {
args.push_back(&result.value);
}
};
/// Invokes the function with the given name passing it the list of arguments
/// by value. Function result can be obtain through output parameter using the
/// `FnResult` wrapper defined above. For example:
///
/// func @foo(%arg0 : i32) -> i32 attributes { llvm.emit_c_interface }
///
/// can be invoked:
///
/// int32_t result = 0;
/// llvm::Error error = jit->invoke("foo", 42,
/// result(result));
template <typename... Args>
llvm::Error invoke(llvm::StringRef funcName, Args... args) {
const std::string adapterName = std::string("") + funcName.str();
llvm::SmallVector<void *> argsArray;
// Pack every arguments in an array of pointers. Delegate the packing to a
// trait so that it can be overridden per argument type.
// TODO: replace with a fold expression when migrating to C++17.
int dummy[] = {0, ((void)Argument<Args>::pack(argsArray, args), 0)...};
(void)dummy;
return invokePacked(adapterName, argsArray);
};
/// Dump object code to output file `filename`.
void dumpToObjectFile(llvm::StringRef filename);
/// Register symbols with this ExecutionEngine.
void registerSymbols(
llvm::function_ref<llvm::orc::SymbolMap(llvm::orc::MangleAndInterner)>
symbolMap);
std::unique_ptr<exprs::Expression> eval(SereneContext &ctx,
std::string input);
};
} // namespace serene
#endif

View File

@ -0,0 +1,7 @@
#ifndef LLVM_IR_VALUE_H
#define LLVM_IR_VALUE_H
#pragma clang diagnostic ignored "-Wunused-parameter"
#include <llvm/IR/Value.h>
#endif

View File

@ -0,0 +1,56 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef LLVM_PATCHES_H
#define LLVM_PATCHES_H
#include <llvm/ADT/DenseMap.h>
namespace llvm {
// Our specialization of DensMapInfo for string type. This will allow use to use
// string
template <>
struct DenseMapInfo<std::string> {
static inline std::string getEmptyKey() { return ""; }
static inline std::string getTombstoneKey() {
// Maybe we need to use something else beside strings ????
return "0TOMBED";
}
static unsigned getHashValue(const std::string &Val) {
assert(Val != getEmptyKey() && "Cannot hash the empty key!");
assert(Val != getTombstoneKey() && "Cannot hash the tombstone key!");
return (unsigned)(llvm::hash_value(Val));
}
static bool isEqual(const std::string &LHS, const std::string &RHS) {
if (RHS == getEmptyKey()) {
return LHS == getEmptyKey();
}
if (RHS == getTombstoneKey()) {
return LHS == getTombstoneKey();
}
return LHS == RHS;
}
};
} // namespace llvm
#endif

143
include/serene/namespace.h Normal file
View File

@ -0,0 +1,143 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
/**
* Commentary:
* Rules of a namespace:
* - A namespace has have a name and it has to own it.
* - A namespace may or may not be assiciated with a file
* - The internal AST of a namespace is an evergrowing tree which may expand at
* any given time. For example via iteration of a REPL
*/
#ifndef SERENE_NAMESPACE_H
#define SERENE_NAMESPACE_H
#include "serene/environment.h"
#include "serene/errors/error.h"
#include "serene/export.h"
#include "serene/slir/generatable.h"
#include "serene/traits.h"
#include "serene/utils.h"
#include <llvm/ADT/SmallString.h>
#include <llvm/ADT/StringRef.h>
#include <llvm/ADT/Twine.h>
#include <llvm/IR/Module.h>
#include <mlir/IR/Builders.h>
#include <mlir/IR/BuiltinOps.h>
#include <mlir/IR/OwningOpRef.h>
#include <mlir/IR/Value.h>
#include <mlir/Support/LogicalResult.h>
#include <atomic>
#include <memory>
#include <string>
#define NAMESPACE_LOG(...) \
DEBUG_WITH_TYPE("NAMESPACE", llvm::dbgs() << __VA_ARGS__ << "\n");
namespace serene {
class SereneContext;
namespace exprs {
class Expression;
using Node = std::shared_ptr<Expression>;
using Ast = std::vector<Node>;
} // namespace exprs
using MaybeModule = llvm::Optional<std::unique_ptr<llvm::Module>>;
using MaybeModuleOp = llvm::Optional<mlir::OwningOpRef<mlir::ModuleOp>>;
/// Serene's namespaces are the unit of compilation. Any code that needs to be
/// compiled has to be in a namespace. The official way to create a new
/// namespace is to use the `makeNamespace` function.
class SERENE_EXPORT Namespace {
private:
SereneContext &ctx;
// Anonymous function counter. We need to assing a unique name to each
// anonymous function and we use this counter to generate those names
std::atomic<uint> fn_counter = 0;
/// The content of the namespace. It should alway hold a semantically
/// correct AST. It means thet the AST that we want to stor here has
/// to pass the semantic analyzer.
exprs::Ast tree;
public:
std::string name;
llvm::Optional<std::string> filename;
/// The root environment of the namespace on the semantic analysis phase.
/// Which is a mapping from names to AST nodes ( no evaluation ).
Environment<std::string, exprs::Node> semanticEnv;
/// Th root environmanet to store the MLIR value during the IR generation
/// phase.
Environment<llvm::StringRef, mlir::Value> symbolTable;
Namespace(SereneContext &ctx, llvm::StringRef ns_name,
llvm::Optional<llvm::StringRef> filename);
exprs::Ast &getTree();
/// Expand the current tree of the namespace with the given \p ast by
/// semantically analazing it first. If the give \p ast in not valid
/// it will return analysis errors.
errors::OptionalErrors expandTree(exprs::Ast &ast);
/// Increase the function counter by one
uint nextFnCounter();
SereneContext &getContext();
// TODO: Fix the return type and use a `llvm::Optional` instead
/// Generate and return a MLIR ModuleOp tha contains the IR of the namespace
/// with respect to the compilation phase
MaybeModuleOp generate();
/// Compile the namespace to a llvm module. It will call the
/// `generate` method of the namespace to generate the IR.
MaybeModule compileToLLVM();
/// Run all the passes specified in the context on the given MLIR ModuleOp.
mlir::LogicalResult runPasses(mlir::ModuleOp &m);
/// Dumps the namespace with respect to the compilation phase
void dump();
void enqueueError(llvm::StringRef e) const;
~Namespace();
};
using NSPtr = std::shared_ptr<Namespace>;
using MaybeNS = Result<NSPtr, errors::ErrorTree>;
/// Create a naw namespace with the given `name` and optional `filename` and
/// return a shared pointer to it in the given Serene context. If the
/// `setCurrent` argument is set to true, the created NS will become the
/// curret namespace in the context
SERENE_EXPORT NSPtr makeNamespace(SereneContext &ctx, llvm::StringRef name,
llvm::Optional<llvm::StringRef> filename,
bool setCurrent = true);
} // namespace serene
#endif

35
include/serene/passes.h Normal file
View File

@ -0,0 +1,35 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_PASSES_H
#define SERENE_PASSES_H
#include <mlir/Pass/Pass.h>
namespace serene::passes {
/// Return a pass to convert SLIR dialect to built-in dialects
/// of MLIR.
std::unique_ptr<mlir::Pass> createSLIRLowerToMLIRPass();
/// Return a pass to convert different dialects of MLIR to LLVM dialect.
std::unique_ptr<mlir::Pass> createSLIRLowerToLLVMDialectPass();
} // namespace serene::passes
#endif

View File

@ -1,7 +1,7 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2024 Sameer Rahmani <lxsameer@gnu.org>
* Copyright (c) 2019-2021 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
@ -16,8 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LOCATION_H
#define LOCATION_H
#ifndef SERENE_READER_LOCATION_H
#define SERENE_READER_LOCATION_H
#include <mlir/IR/Diagnostics.h>
#include <mlir/IR/Location.h>
@ -25,6 +25,9 @@
#include <string>
namespace serene {
class SereneContext;
namespace reader {
/// It represents a location in the input string to the parser via `line`,
struct Location {
@ -32,7 +35,7 @@ struct Location {
/// a namespace in hand
llvm::StringRef ns;
std::optional<llvm::StringRef> filename = std::nullopt;
llvm::Optional<llvm::StringRef> filename = llvm::None;
/// A pointer to the character that this location is pointing to
/// it the input buffer
const char *c = nullptr;
@ -47,23 +50,21 @@ struct Location {
::std::string toString() const;
Location() = default;
explicit Location(llvm::StringRef ns,
std::optional<llvm::StringRef> fname = std::nullopt,
const char *c = nullptr, unsigned short int line = 0,
unsigned short int col = 0, bool knownLocation = true)
Location(llvm::StringRef ns,
llvm::Optional<llvm::StringRef> fname = llvm::None,
const char *c = nullptr, unsigned short int line = 0,
unsigned short int col = 0, bool knownLocation = true)
: ns(ns), filename(fname), c(c), line(line), col(col),
knownLocation(knownLocation){};
Location clone() const;
// mlir::Location toMLIRLocation(mlir::MLIRContext &ctx);
mlir::Location toMLIRLocation(SereneContext &ctx);
/// Returns an unknown location for the given \p ns.
static Location UnknownLocation(llvm::StringRef ns) {
return Location(ns, std::nullopt, nullptr, 0, 0, false);
return Location(ns, llvm::None, nullptr, 0, 0, false);
}
~Location() = default;
};
class LocationRange {
@ -72,25 +73,20 @@ public:
Location end;
LocationRange() = default;
explicit LocationRange(Location _start) : start(_start), end(_start){};
LocationRange(Location _start) : start(_start), end(_start){};
LocationRange(Location _start, Location _end) : start(_start), end(_end){};
// LocationRange(const LocationRange &);
LocationRange(LocationRange &lr) : start(lr.start), end(lr.end){};
LocationRange(const LocationRange &lr) : start(lr.start), end(lr.end){};
bool isKnownLocation() const { return start.knownLocation; };
static LocationRange UnknownLocation(llvm::StringRef ns) {
return LocationRange(Location::UnknownLocation(ns));
}
~LocationRange() = default;
};
void incLocation(Location &, const char *);
void decLocation(Location &, const char *);
} // namespace reader
} // namespace serene
#endif

View File

@ -1,7 +1,7 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2024 Sameer Rahmani <lxsameer@gnu.org>
* Copyright (c) 2019-2021 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
@ -18,8 +18,8 @@
/**
* Commentary:
* `Reader` is the base parser class and accepts a buffer like object (usually
* `llvm::StringRef`) as the input and parses it to create an AST (look at the
* `Reader` is the base parser class and accepts a buffer like objenct (usually
* `llvm::StringRef`) as the input and parsess it to create an AST (look at the
* `serene::exprs::Expression` class).
*
* The parsing algorithm is quite simple and it is a LL(2). It means that, we
@ -34,37 +34,50 @@
* case contains the node and an `Error` on the failure case.
*/
#ifndef READER_H
#define READER_H
#ifndef SERENE_READER_READER_H
#define SERENE_READER_READER_H
#include "ast/ast.h"
#include "location.h"
#include "serene/errors.h"
#include "serene/exprs/expression.h"
#include "serene/exprs/list.h"
#include "serene/exprs/symbol.h"
#include "serene/reader/location.h"
#include "serene/serene.h"
#include <llvm/ADT/StringRef.h>
#include <system_error>
#include <llvm/Support/Debug.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/Support/MemoryBufferRef.h>
#include <llvm/Support/raw_ostream.h>
#include <memory>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
#define READER_LOG(...) \
DEBUG_WITH_TYPE("READER", llvm::dbgs() \
<< "[READER]: " << __VA_ARGS__ << "\n");
namespace serene {
namespace jit {
class JIT;
} // namespace jit
namespace serene::reader {
/// Base reader class which reads from a string directly.
class Reader {
private:
llvm::StringRef ns;
std::optional<llvm::StringRef> filename;
SereneContext &ctx;
const char *currentChar = nullptr;
llvm::StringRef ns;
llvm::Optional<llvm::StringRef> filename;
const char *currentChar = NULL;
llvm::StringRef buf;
/// The position tracker that we will use to determine the end of the
/// buffer since the buffer might not be null terminated
size_t currentPos = static_cast<size_t>(-1);
size_t currentPos = -1;
Location currentLocation;
@ -85,36 +98,38 @@ private:
static bool isValidForIdentifier(char c);
// The property to store the ast tree
ast::Ast ast;
exprs::Ast ast;
ast::MaybeNode readSymbol();
ast::MaybeNode readNumber(bool);
ast::MaybeNode readList();
ast::MaybeNode readExpr();
exprs::MaybeNode readSymbol();
exprs::MaybeNode readNumber(bool);
exprs::MaybeNode readList();
exprs::MaybeNode readExpr();
bool isEndOfBuffer(const char *);
public:
Reader(llvm::StringRef buf, llvm::StringRef ns,
std::optional<llvm::StringRef> filename);
Reader(llvm::MemoryBufferRef buf, llvm::StringRef ns,
std::optional<llvm::StringRef> filename);
Reader(SereneContext &ctx, llvm::StringRef buf, llvm::StringRef ns,
llvm::Optional<llvm::StringRef> filename);
Reader(SereneContext &ctx, llvm::MemoryBufferRef buf, llvm::StringRef ns,
llvm::Optional<llvm::StringRef> filename);
// void setInput(const llvm::StringRef string);
/// Parses the the input and creates a possible AST out of it or errors
/// otherwise.
ast::MaybeAst read();
exprs::MaybeAst read();
~Reader();
};
/// Parses the given `input` string and returns a `Result<ast>`
/// which may contains an AST or an `llvm::Error`
ast::MaybeAst read(llvm::StringRef input, llvm::StringRef ns,
std::optional<llvm::StringRef> filename);
ast::MaybeAst read(llvm::MemoryBufferRef input, llvm::StringRef ns,
std::optional<llvm::StringRef> filename);
exprs::MaybeAst read(SereneContext &ctx, llvm::StringRef input,
llvm::StringRef ns,
llvm::Optional<llvm::StringRef> filename);
exprs::MaybeAst read(SereneContext &ctx, llvm::MemoryBufferRef input,
llvm::StringRef ns,
llvm::Optional<llvm::StringRef> filename);
} // namespace serene::reader
} // namespace serene
#endif

View File

@ -0,0 +1,43 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_READER_SEMANTICS_H
#define SERENE_READER_SEMANTICS_H
#include "serene/context.h"
#include "serene/errors/error.h"
#include "serene/exprs/expression.h"
namespace serene::reader {
using AnalyzeResult = Result<exprs::Ast, std::vector<errors::ErrorPtr>>;
/// The entry point to the Semantic analysis phase. It calls the `analyze`
/// method of each node in the given AST and creates a new AST that contains a
/// more comprehensive set of nodes in a semantically correct AST. If the
/// `analyze` method of a node return a `nullptr` value as the `success` result
/// (Checkout the `Result` type in `utils.h`) then the original node will be
/// used instead. Also please note that in **Serene** Semantic errors
/// represented as AST nodes as well. So you should expect an `analyze` method
/// of a node to return a `Result<node>::Success(Error...)` in case of a
/// semantic error.
///
/// \param ctx The semantic analysis context
/// \param inputAst The raw AST to analyze and possibly rewrite.
AnalyzeResult analyze(serene::SereneContext &ctx, exprs::Ast &inputAst);
}; // namespace serene::reader
#endif

View File

@ -0,0 +1,40 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_READER_TRAITS_H
#define SERENE_READER_TRAITS_H
#include "serene/reader/location.h"
#include "serene/traits.h"
namespace serene::reader {
template <typename ConcreteType>
class ILocatable : public TraitBase<ConcreteType, ILocatable> {
public:
ILocatable(){};
ILocatable(const ILocatable &) = delete;
serene::reader::LocationRange &where() const {
return this->Object().where();
}
};
template <typename T>
serene::reader::LocationRange &where(ILocatable<T> &);
} // namespace serene::reader
#endif

80
include/serene/serene.h Normal file
View File

@ -0,0 +1,80 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_SERENE_H
#define SERENE_SERENE_H
#include "serene/config.h"
#include "serene/context.h"
#include "serene/export.h"
#include "serene/exprs/expression.h"
#include "serene/source_mgr.h"
namespace serene {
/// Clinet applications have to call this function before any interaction with
/// the Serene's compiler API.
SERENE_EXPORT void initCompiler();
/// Register the global CLI options of the serene compiler. If the client
/// application needs to setup the compilers options automatically use this
/// function in conjunction with `applySereneCLOptions`.
SERENE_EXPORT void registerSereneCLOptions();
/// Applies the global compiler options on the give \p SereneContext. This
/// function has to be called after `llvm::cl::ParseCommandLineOptions`.
SERENE_EXPORT void applySereneCLOptions(SereneContext &ctx);
/// Reads the the given \p input as a Serene source code in the given
/// \c SereneContext \p ctx and returns the possible AST tree of the input or an
/// error otherwise.
///
/// In case of an error Serene will throw the error messages vis the diagnostic
/// engine as well and the error that this function returns will be the generic
/// error message.
///
/// Be aware than this function reads the input in the context of the current
/// namespace. So for example if the input is somthing like:
///
/// (ns example.code) ....
///
/// and the current ns is `user` then if there is a syntax error in the input
/// the error will be reported under the `user` ns. This is logical because
/// this function reads the code and not evaluate it. the `ns` form has to be
/// evaluated in order to change the ns.
SERENE_EXPORT exprs::MaybeAst read(SereneContext &ctx, std::string &input);
/// Evaluates the given AST form \p input in the given \c SereneContext \p ctx
/// and retuns a new expression as the result or a possible error.
///
/// In case of an error Serene will throw the error messages vis the diagnostic
/// engine as well and the error that this function returns will be the
/// generic error message.
// SERENE_EXPORT exprs::MaybeNode eval(SereneContext &ctx, exprs::Ast input);
// TODO: Return a Serene String type instead of the std::string
// TODO: Create an overload to get a stream instead of the result string
/// Prints the given AST form \p input in the given \c SereneContext \p ctx
/// into the given \p result.
/// Note: print is a lisp action. Don't confuse it with a print function such
/// as `println`.
SERENE_EXPORT void print(SereneContext &ctx, const exprs::Ast &input,
std::string &result);
} // namespace serene
#endif

View File

@ -0,0 +1,6 @@
set(LLVM_TARGET_DEFINITIONS dialect.td)
mlir_tablegen(ops.h.inc -gen-op-decls)
mlir_tablegen(ops.cpp.inc -gen-op-defs)
mlir_tablegen(dialect.h.inc -gen-dialect-decls)
mlir_tablegen(dialect.cpp.inc -gen-dialect-defs)
add_public_tablegen_target(SereneDialectGen)

View File

@ -0,0 +1,37 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_SLIR_DIALECT_H
#define SERENE_SLIR_DIALECT_H
#include <mlir/IR/BuiltinOps.h>
#include <mlir/IR/Dialect.h>
#include <mlir/Interfaces/ControlFlowInterfaces.h>
#include <mlir/Interfaces/SideEffectInterfaces.h>
// Include the auto-generated header file containing the declaration of the
// serene's dialect.
#include "serene/slir/dialect.h.inc"
// Include the auto-generated header file containing the declarations of the
// serene's operations.
// for more on GET_OP_CLASSES: https://mlir.llvm.org/docs/OpDefinitions/
#define GET_OP_CLASSES
#include "serene/slir/ops.h.inc"
#endif // SERENE_SLIR_DIALECT_H

View File

@ -0,0 +1,98 @@
#ifndef SERENE_DIALECT
#define SERENE_DIALECT
include "mlir/IR/OpBase.td"
include "mlir/IR/OpAsmInterface.td"
include "mlir/IR/SymbolInterfaces.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
include "mlir/Interfaces/CallInterfaces.td"
include "mlir/Interfaces/CastInterfaces.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
include "mlir/Interfaces/ControlFlowInterfaces.td"
include "mlir/Interfaces/DataLayoutInterfaces.td"
include "mlir/Interfaces/VectorInterfaces.td"
// Dialect definition. It will directly generate the SereneDialect class
def Serene_Dialect : Dialect {
let name = "serene";
let cppNamespace = "::serene::slir";
let summary = "Primary IR of serene language.";
let description = [{
This dialect tries to map the special forms of a lisp into
IR level operations.
}];
}
// Base class for Serene dialect operations. This operation inherits from the base
// `Op` class in OpBase.td, and provides:
// * The parent dialect of the operation.
// * The mnemonic for the operation, or the name without the dialect prefix.
// * A list of traits for the operation.
class Serene_Op<string mnemonic, list<OpTrait> traits = []> :
Op<Serene_Dialect, mnemonic, traits>;
// All of the types will extend this class.
class Serene_Type<string name> : TypeDef<Serene_Dialect, name> { }
def ValueOp: Serene_Op<"value"> {
let summary = "This operation represent a value";
let description = [{
ValueOp
}];
let arguments = (ins I64Attr:$value);
let results = (outs I64);
//let verifier = [{ return serene::sir::verify(*this); }];
let builders = [
OpBuilder<(ins "int":$value), [{
// Build from fix 64 bit int
build(odsBuilder, odsState, odsBuilder.getI64Type(), (uint64_t) value);
}]>,
];
}
// TODO: Add the FunctionLike trait here and include its header file in dialect.h
def FnOp: Serene_Op<"fn", [
AffineScope, AutomaticAllocationScope,
IsolatedFromAbove,
]> {
let summary = "This operation is just a place holder for a function";
let description = [{
A place holder for an anonymous function. For example consider an expression
like `(def a (fn (x) x))`, in this case we don't immediately create an anonymous
function since we need to set the name and create the function later.
}];
let arguments = (ins StrAttr:$name,
DictionaryAttr:$args,
OptionalAttr<StrAttr>:$sym_visibility);
let regions = (region AnyRegion:$body);
let results = (outs I64);
}
def ReturnOp: Serene_Op<"return", [NoSideEffect, HasParent<"FnOp">,
ReturnLike, Terminator]> {
let summary = "This operation marks the return value of a function";
let description = [{
ReturnOp
}];
let arguments = (ins AnyType:$operand);
let assemblyFormat =
[{ attr-dict $operand `:` type($operand) }];
}
#endif // SERENE_DIALECT

View File

@ -0,0 +1,120 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_SLIR_GENERATABLE_H
#define SERENE_SLIR_GENERATABLE_H
#include "serene/slir/dialect.h"
#include "serene/traits.h"
#include <llvm/ADT/STLExtras.h>
#include <llvm/IR/Module.h>
#include <llvm/Support/Casting.h>
#include <llvm/Support/TargetSelect.h>
#include <mlir/ExecutionEngine/ExecutionEngine.h>
#include <mlir/ExecutionEngine/OptUtils.h>
#include <mlir/IR/BuiltinOps.h>
#include <mlir/IR/MLIRContext.h>
#include <mlir/Support/LogicalResult.h>
#include <mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h>
#include <mlir/Target/LLVMIR/ModuleTranslation.h>
#include <stdexcept>
#include <utility>
namespace serene {
class Namespace;
class SereneContext;
} // namespace serene
namespace serene::slir {
template <typename T>
class GeneratableUnit : public TraitBase<T, GeneratableUnit> {
public:
GeneratableUnit(){};
GeneratableUnit(const GeneratableUnit &) = delete;
void generate(serene::Namespace &ns) {
// TODO: should we return any status or possible error here or
// should we just populate them in a ns wide state?
this->Object().generateIR(ns);
};
};
template <typename T>
class Generatable : public TraitBase<T, Generatable> {
public:
Generatable(){};
Generatable(const Generatable &) = delete;
mlir::LogicalResult generate() { return this->Object().generate(); };
mlir::LogicalResult runPasses() { return this->Object().runPasses(); };
mlir::ModuleOp &getModule() { return this->Object().getModule(); };
serene::SereneContext &getContext() { return this->Object().getContext(); };
void dump() { this->Object().dump(); };
};
template <typename T>
mlir::LogicalResult generate(Generatable<T> &t) {
return t.generate();
};
template <typename T>
std::unique_ptr<llvm::Module> toLLVMIR(Generatable<T> &t) {
auto &module = t.getModule();
auto &ctx = t.getContext();
// Register the translation to LLVM IR with the MLIR context.
mlir::registerLLVMDialectTranslation(ctx.mlirContext);
// Convert the module to LLVM IR in a new LLVM IR context.
auto llvmModule = mlir::translateModuleToLLVMIR(module, ctx.llvmContext);
if (!llvmModule) {
// TODO: Return a Result type instead
llvm::errs() << "Failed to emit LLVM IR\n";
throw std::runtime_error("Failed to emit LLVM IR\n");
}
// Initialize LLVM targets.
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
// TODO: replace this call with our own version of setupTargetTriple
mlir::ExecutionEngine::setupTargetTriple(llvmModule.get());
/// Optionally run an optimization pipeline over the llvm module.
auto optPipeline = mlir::makeOptimizingTransformer(
/*optLevel=*/ctx.getOptimizatioLevel(), /*sizeLevel=*/0,
/*targetMachine=*/nullptr);
if (auto err = optPipeline(llvmModule.get())) {
llvm::errs() << "Failed to optimize LLVM IR " << err << "\n";
throw std::runtime_error("Failed to optimize LLVM IR");
}
return std::move(llvmModule);
};
template <typename T>
void dump(Generatable<T> &t) {
t.dump();
};
} // namespace serene::slir
#endif

View File

@ -1,7 +1,7 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2024 Sameer Rahmani <lxsameer@gnu.org>
* Copyright (c) 2019-2021 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
@ -15,16 +15,21 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SERENE_SLIR_SLIR_H
#define SERENE_SLIR_SLIR_H
namespace llvm {
class RecordKeeper;
class raw_ostream;
} // namespace llvm
#include "serene/exprs/expression.h"
#define DEBUG_TYPE "errors-backend"
#include <mlir/IR/BuiltinOps.h>
#include <mlir/IR/MLIRContext.h>
#include <memory>
namespace serene {
void emitErrors(llvm::RecordKeeper &rk, llvm::raw_ostream &os);
namespace slir {
std::unique_ptr<llvm::Module> compileToLLVMIR(serene::SereneContext &ctx,
mlir::ModuleOp &module);
} // namespace slir
} // namespace serene
#endif

View File

@ -0,0 +1,116 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
#ifndef SERENE_SLIR_TRAITS_H
#define SERENE_SLIR_TRAITS_H
#include "serene/slir/dialect.h"
#include "serene/traits.h"
#include <llvm/ADT/STLExtras.h>
#include <llvm/IR/Module.h>
#include <llvm/Support/Casting.h>
#include <llvm/Support/TargetSelect.h>
#include <mlir/ExecutionEngine/ExecutionEngine.h>
#include <mlir/ExecutionEngine/OptUtils.h>
#include <mlir/IR/BuiltinOps.h>
#include <mlir/IR/MLIRContext.h>
#include <mlir/Support/LogicalResult.h>
#include <mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h>
#include <mlir/Target/LLVMIR/ModuleTranslation.h>
#include <stdexcept>
#include <utility>
namespace serene {
class Namespace;
class SereneContext;
} // namespace serene
namespace serene::slir {
template <typename T>
class GeneratableUnit : public TraitBase<T, GeneratableUnit> {
public:
GeneratableUnit(){};
GeneratableUnit(const GeneratableUnit &) = delete;
void generate(serene::Namespace &ns) { this->Object().generateIR(ns); };
};
template <typename T>
class Generatable : public TraitBase<T, Generatable> {
public:
Generatable(){};
Generatable(const Generatable &) = delete;
mlir::LogicalResult generate() { return this->Object().generate(); };
mlir::LogicalResult runPasses() { return this->Object().runPasses(); };
mlir::ModuleOp &getModule() { return this->Object().getModule(); };
serene::SereneContext &getContext() { return this->Object().getContext(); };
void dump() { this->Object().dump(); };
};
template <typename T>
mlir::LogicalResult generate(Generatable<T> &t) {
return t.generate();
};
template <typename T>
std::unique_ptr<llvm::Module> toLLVMIR(Generatable<T> &t) {
auto &module = t.getModule();
auto &ctx = t.getContext();
// Register the translation to LLVM IR with the MLIR context.
mlir::registerLLVMDialectTranslation(ctx.mlirContext);
// Convert the module to LLVM IR in a new LLVM IR context.
auto llvmModule = mlir::translateModuleToLLVMIR(module, ctx.llvmContext);
if (!llvmModule) {
// TODO: Return a Result type instead
llvm::errs() << "Failed to emit LLVM IR\n";
throw std::runtime_error("Failed to emit LLVM IR\n");
}
// Initialize LLVM targets.
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
// TODO: replace this call with our own version of setupTargetTriple
mlir::ExecutionEngine::setupTargetTriple(llvmModule.get());
/// Optionally run an optimization pipeline over the llvm module.
auto optPipeline = mlir::makeOptimizingTransformer(
/*optLevel=*/ctx.getOptimizatioLevel(), /*sizeLevel=*/0,
/*targetMachine=*/nullptr);
if (auto err = optPipeline(llvmModule.get())) {
llvm::errs() << "Failed to optimize LLVM IR " << err << "\n";
throw std::runtime_error("Failed to optimize LLVM IR");
}
return std::move(llvmModule);
};
template <typename T>
void dump(Generatable<T> &t) {
t.dump();
};
} // namespace serene::slir
#endif

View File

@ -1,7 +1,7 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2024 Sameer Rahmani <lxsameer@gnu.org>
* Copyright (c) 2019-2021 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
@ -16,16 +16,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "serene/core/core.h"
#include "serene/types/types.h"
#ifndef SERENE_SLIR_UTILS_H
#define SERENE_SLIR_UTILS_H
#include <cstdio>
#include "serene/reader/location.h"
#include <mlir/IR/BuiltinOps.h>
namespace serene {
extern "C" int SERENE_EXPORT compile() {
printf("compile11\n");
return 2;
};
class Namespace;
} // namespace serene
namespace serene::slir {
/**
* Convert a Serene location to MLIR FileLineLoc Location
*/
::mlir::Location toMLIRLocation(serene::Namespace &,
serene::reader::Location &);
} // namespace serene::slir
#endif

View File

@ -1,7 +1,7 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2024 Sameer Rahmani <lxsameer@gnu.org>
* Copyright (c) 2019-2021 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
@ -19,8 +19,8 @@
#ifndef SERENE_SOURCE_MGR_H
#define SERENE_SOURCE_MGR_H
#include "ast/ast.h"
#include "location.h"
#include "serene/namespace.h"
#include "serene/reader/location.h"
#include <llvm/ADT/SmallVector.h>
#include <llvm/ADT/StringMap.h>
@ -32,16 +32,13 @@
#include <mlir/Support/Timing.h>
#include <memory>
#include <string>
#define SMGR_LOG(...) \
DEBUG_WITH_TYPE("sourcemgr", llvm::dbgs() \
<< "[SMGR]: " << __VA_ARGS__ << "\n");
namespace serene {
namespace jit {
class JIT;
} // namespace jit
class SereneContext;
/// This class is quite similar to the `llvm::SourceMgr` in functionality. We
/// even borrowed some of the code from the original implementation but removed
@ -55,16 +52,16 @@ class JIT;
///
/// Later on, whenever we need to refer to the source file of a namespace for
/// diagnosis purposes or any other purpose we can use the functions in this
/// class to get hold of a pointer to a specific `Location` of the
/// class to get hold of a pointer to a specific `reader::Location` of the
/// buffer.
///
/// Note: Unlike the original version, SourceMgr does not handle the diagnostics
/// and it uses the Serene's `DiagnosticEngine` for that matter.
class SourceMgr {
class SERENE_EXPORT SourceMgr {
public:
// TODO: Make it a vector of supported suffixes
constexpr static const char *DEFAULT_SUFFIX = "srn";
std::string DEFAULT_SUFFIX = "srn";
private:
struct SrcBuffer {
@ -98,11 +95,11 @@ private:
/// This is the location of the parent import or unknown location if it is
/// the main namespace
LocationRange importLoc;
reader::LocationRange importLoc;
SrcBuffer() = default;
SrcBuffer(SrcBuffer &&) noexcept;
SrcBuffer(const SrcBuffer &) = delete;
SrcBuffer(const SrcBuffer &) = delete;
SrcBuffer &operator=(const SrcBuffer &) = delete;
~SrcBuffer();
};
@ -131,12 +128,12 @@ private:
static std::string convertNamespaceToPath(std::string ns_name);
public:
SourceMgr() = default;
SourceMgr(const SourceMgr &) = delete;
SourceMgr() = default;
SourceMgr(const SourceMgr &) = delete;
SourceMgr &operator=(const SourceMgr &) = delete;
SourceMgr(SourceMgr &&) = default;
SourceMgr &operator=(SourceMgr &&) = default;
~SourceMgr() = default;
SourceMgr &operator=(SourceMgr &&) = default;
~SourceMgr() = default;
/// Set the `loadPaths` to the given \p dirs. `loadPaths` is a vector of
/// directories that Serene will look in order to find a file that constains a
@ -174,7 +171,7 @@ public:
/// Add a new source buffer to this source manager. This takes ownership of
/// the memory buffer.
unsigned AddNewSourceBuffer(std::unique_ptr<llvm::MemoryBuffer> f,
const LocationRange &includeLoc);
reader::LocationRange includeLoc);
/// Lookup for a file containing the namespace definition of with given
/// namespace name \p name. In case that the file exists, it returns an
@ -184,7 +181,8 @@ public:
///
/// \p importLoc is a location in the source code where the give namespace is
/// imported.
ast::MaybeNS readNamespace(std::string name, const LocationRange &importLoc);
MaybeNS readNamespace(SereneContext &ctx, std::string name,
reader::LocationRange importLoc);
};
}; // namespace serene

122
include/serene/traits.h Normal file
View File

@ -0,0 +1,122 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2021 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, version 2.
*
* 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/>.
*/
/**
* This is a CRTP based Trait implementation that allows to use Trait like
* classes to create polymorphic functions and API statically at compile type
* without any runtime shenanigans. For more on CRTP checkout:
*
* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
*
* In order to define a trait, use the `TraitBase` class like:
* \code
* template <typename ConcreteType>
* class Blahable : public TraitBase<ConcreteType, Blahable> {}
* \endcode
*
* Every Trait has to take the `ConcreteType` as template argument and pass it
* to the `TraitBase`. Checkout the documentation of `TraitBase` for more info
* on creating a new Trait.
*
* Alongside with each Trait type, you should provide the "Official" interface
* of the Trait via some standalone functions that operates on the Trait type.
* For example Imagine we have a Trait type called `ABC` with two main
* functionality `foo` and `bar`. We need to create two functions as follows:
*
* \code
* template <typename T>
* SomeType Foo(ABC<T> &t) { return t.foo(); };
*
* template <typename T>
* SomeType bar(ABC<T> &t, int x) { return t.bar(x); };
* \endcode
*
* These two functions will be the official interface to the trait `ABC`.
* IMPORTANT NOTE: Make sure to pass a reference of type `ABC<T>` to the
* functions and DO NOT PASS BY COPY. Since copying will copy the value by the
* trait type only, we would not be able to statically case it to the
* implementor type and it will lead to some allocation problem.
*
* Traits can be used via `WithTrait` helper class which provides a clean
* interface to mix and match Trait types.
*
*/
#ifndef SERENE_TRAITS_H
#define SERENE_TRAITS_H
#include <string>
#include <type_traits>
namespace serene {
/// A placeholder structure that replaces the concrete type of the
/// Imlementations Which might have child classes.
struct FinalImpl;
/// In order to use Traits, we can use `WithTrait` class as the base
/// of any implementation class and pass the Trait classes as template argument
/// for example:
///
/// \code
/// class Expression : public WithTrait<Expression, Printable, Locatable> {}
/// \endcode
template <typename ConcreteType, template <typename T> class... Traits>
class WithTrait : public Traits<ConcreteType>... {
protected:
WithTrait(){};
friend ConcreteType;
};
/// This class provides the common functionality among the Trait Types and
/// every Trait has to inherit from this class. Here is an example:
///
/// \code
/// template <typename ConcreteType>
/// class Blahable : public TraitBase<ConcreteType, Blahable> {}
/// \endcode
///
/// In the Trait class the underlaying object which implements the Trait
/// is accessable via the `Object` method.
template <typename ConcreteType, template <typename> class TraitType>
class TraitBase {
protected:
/// Statically casts the object to the concrete type object to be
/// used in the Trait Types.
// const ConcreteType &Object() const {
// return static_cast<const ConcreteType &>(*this);
// };
ConcreteType &Object() { return static_cast<ConcreteType &>(*this); };
};
template <typename ConcreteType>
class IDebuggable : public TraitBase<ConcreteType, IDebuggable> {
public:
IDebuggable(){};
IDebuggable(const IDebuggable &) = delete;
std::string toString() const { return this->Object().toString(); }
};
template <typename T>
std::string toString(IDebuggable<T> &t) {
return t.toString();
}
}; // namespace serene
#endif

View File

@ -1,7 +1,7 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2024 Sameer Rahmani <lxsameer@gnu.org>
* Copyright (c) 2019-2021 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
@ -16,8 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "reader.h"
#ifndef SERENE_TRAITS_LOCATABLE_H
#define SERENE_TRAITS_LOCATABLE_H
#include <gtest/gtest.h>
TEST(Reader, ReadNumber) { EXPECT_EQ(1, 1); }
#endif

View File

@ -1,7 +1,7 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2024 Sameer Rahmani <lxsameer@gnu.org>
* Copyright (c) 2019-2021 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
@ -16,12 +16,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SERENE_COMMANDS_H
#define SERENE_COMMANDS_H
#ifndef SERENE_TYPES_TYPE_H
#define SERENE_TYPES_TYPE_H
namespace serene::commands {
int cc(int argc, char **argv);
int run();
} // namespace serene::commands
#include <string>
namespace serene::types {
class Type {
public:
virtual ~Type() = default;
/// The AST representation of a type
virtual std::string toString() const = 0;
};
}; // namespace serene::types
#endif

View File

@ -1,7 +1,7 @@
/* -*- C++ -*-
* Serene Programming Language
*
* Copyright (c) 2019-2024 Sameer Rahmani <lxsameer@gnu.org>
* Copyright (c) 2019-2021 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
@ -16,8 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UTILS_H
#define UTILS_H
#ifndef SERENE_UTILS_H
#define SERENE_UTILS_H
#include "serene/export.h"
#include <llvm/Support/Error.h>
@ -56,7 +58,7 @@ namespace serene {
///
/// works perfectly.
template <typename T, typename E = llvm::Error>
class Result {
class SERENE_EXPORT Result {
// The actual data container
std::variant<T, E> contents;
@ -67,7 +69,7 @@ class Result {
Result(InPlace i, Content &&c) : contents(i, std::forward<Content>(c)){};
public:
explicit constexpr Result(const T &v)
constexpr Result(const T &v)
: Result(std::in_place_index_t<0>(), std::move(v)){};
/// Return a pointer to the success case value of the result. It is
@ -129,10 +131,5 @@ public:
operator bool() const { return ok(); }
};
inline void makeFQSymbolName(const llvm::StringRef &ns,
const llvm::StringRef &sym, std::string &result) {
result = (ns + "/" + sym).str();
};
} // namespace serene
#endif

View File

@ -0,0 +1,92 @@
// DO NOT EDIT THIS FILE: It is aute generated by './builder
// gen_precompile_index'
#ifndef SERENE_PRECOMPIL_H
#define SERENE_PRECOMPIL_H
#include "mlir/Dialect/StandardOps/IR/Ops.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Dialect.h"
#include "mlir/IR/Identifier.h"
#include "mlir/IR/Location.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/Value.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
#include "mlir/Support/LogicalResult.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MemoryBuffer.h"
#include <llvm/ADT/ArrayRef.h>
#include <llvm/ADT/Optional.h>
#include <llvm/ADT/STLExtras.h>
#include <llvm/ADT/SmallString.h>
#include <llvm/ADT/StringRef.h>
#include <llvm/ExecutionEngine/JITEventListener.h>
#include <llvm/ExecutionEngine/ObjectCache.h>
#include <llvm/ExecutionEngine/Orc/CompileUtils.h>
#include <llvm/ExecutionEngine/Orc/ExecutionUtils.h>
#include <llvm/ExecutionEngine/Orc/IRCompileLayer.h>
#include <llvm/ExecutionEngine/Orc/IRTransformLayer.h>
#include <llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h>
#include <llvm/ExecutionEngine/Orc/LLJIT.h>
#include <llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Value.h>
#include <llvm/Support/Casting.h>
#include <llvm/Support/CodeGen.h>
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/Debug.h>
#include <llvm/Support/ErrorHandling.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/FormatVariadic.h>
#include <llvm/Support/Host.h>
#include <llvm/Support/Path.h>
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/ToolOutputFile.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Target/TargetMachine.h>
#include <llvm/Target/TargetOptions.h>
#include <mlir/Conversion/AffineToStandard/AffineToStandard.h>
#include <mlir/Conversion/SCFToStandard/SCFToStandard.h>
#include <mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h>
#include <mlir/Conversion/StandardToLLVM/ConvertStandardToLLVMPass.h>
#include <mlir/Dialect/Affine/IR/AffineOps.h>
#include <mlir/Dialect/LLVMIR/LLVMDialect.h>
#include <mlir/Dialect/MemRef/IR/MemRef.h>
#include <mlir/Dialect/SCF/SCF.h>
#include <mlir/Dialect/StandardOps/IR/Ops.h>
#include <mlir/ExecutionEngine/ExecutionEngine.h>
#include <mlir/ExecutionEngine/OptUtils.h>
#include <mlir/IR/Block.h>
#include <mlir/IR/Builders.h>
#include <mlir/IR/BuiltinOps.h>
#include <mlir/IR/MLIRContext.h>
#include <mlir/IR/OperationSupport.h>
#include <mlir/IR/OwningOpRef.h>
#include <mlir/IR/Value.h>
#include <mlir/Pass/Pass.h>
#include <mlir/Pass/PassManager.h>
#include <mlir/Support/FileUtilities.h>
#include <mlir/Support/LLVM.h>
#include <mlir/Support/LogicalResult.h>
#include <mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h>
#include <mlir/Target/LLVMIR/ModuleTranslation.h>
#include <mlir/Transforms/DialectConversion.h>
#endif

View File

@ -1,27 +0,0 @@
\documentclass{article}
\title{Serene's mathematical cheatsheet}
\author{Sameer Rahmani}
\date{January 2024}
\NeedsTeXFormat{LaTeX2e}
\usepackage[default,light,semibold]{sourcesanspro}
\setsansfont{Source Sans Pro}
\usepackage{etoolbox}
\usepackage{titlesec}
\usepackage{fontspec}
\usepackage[left=0.6in,top=0.3in,right=0.6in,bottom=0.6in]{geometry} % Document margins
\usepackage{hyperref}
\usepackage{mfirstuc}
\edef\restoreparindent{\parindent=\the\parindent\relax}
\usepackage{parskip}
\restoreparindent{}
\pagestyle{empty}
\begin{document}
\maketitle
\newpage
\end{document}

View File

@ -1,135 +0,0 @@
site_name: Serene Programming Language
site_description: A modern, typed lisp
site_author: lxsameer
repo_url: https://devheroes.codes/serene/serene
repo_name: Serene
copyright: Copyright &copy; 2019 - 2023 Sameer Rahmani
edit_uri: _edit/master/docs/pages/
docs_dir: ./docs/pages
site_dir: ./build/docs
nav:
- Home: 'index.md'
- Getting Started: 'getting_started.md'
- Resources: 'resources.md'
theme:
name: material
logo: /images/serene.png
favicon: /images/serene.png
icon:
repo: fontawesome/brands/git-alt
edit: material/pencil
view: material/eye
features:
- content.action.edit
- navigation.tracking
- navigation.instant
- navigation.tabs
- navigation.tabs.sticky
- navigation.sections
- navigation.expand
- navigation.indexes
- toc.follow
- toc.integrate
- navigation.top
- search.suggest
- search.highlight
- search.share
- header.autohide
- navigation.footer
- content.code.copy
- content.code.annotate
palette:
- scheme: slate
# toggle:
# icon: material/brightness-4
# name: Switch to light mode
primary: deep purple
accent: amber
# # Palette toggle for light mode
# - scheme: default
# toggle:
# icon: material/brightness-7
# name: Switch to dark mode
# primary: deep purple
# accent: amber
# # Palette toggle for dark mode
plugins:
- git-revision-date-localized:
enable_creation_date: true
- search
# - social:
# concurrency: 16
- tags
#tags_file: tags.md
- mike:
# These fields are all optional; the defaults are as below...
alias_type: symlink
redirect_template: null
deploy_prefix: ''
canonical_version: null
version_selector: true
css_dir: css
javascript_dir: js
extra:
version:
provider: mike
social:
- icon: fontawesome/brands/mastodon
link: https://social.lxsameer.com/@lxsameer
- icon: fontawesome/brands/twitter
link: https://twitter.com/@lxsameer
- icon: fontawesome/brands/youtube
link: https://www.youtube.com/c/lxsameer
generator: false
extra_css:
- stylesheets/extra.css
markdown_extensions:
- attr_list
- md_in_html
- def_list
- footnotes
- tables
- md_in_html
- pymdownx.superfences
- admonition
- pymdownx.details
- pymdownx.highlight:
anchor_linenums: true
line_spans: __span
pygments_lang_class: true
- pymdownx.inlinehilite
- pymdownx.snippets
- pymdownx.superfences
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format
- pymdownx.tasklist:
custom_checkbox: true
- pymdownx.emoji:
emoji_index: !!python/name:materialx.emoji.twemoji
emoji_generator: !!python/name:materialx.emoji.to_svg
- pymdownx.arithmatex:
generic: true
extra_javascript:
- javascripts/mathjax.js
- https://polyfill.io/v3/polyfill.min.js?features=es6
- https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js

View File

@ -1,76 +0,0 @@
{ lib,
stdenv,
fetchurl,
nixVersions,
libatomic_ops,
cmake,
ninja,
}:
stdenv.mkDerivation (finalAttrs: rec {
pname = "boehmgc";
version = "8.2.4";
src = fetchurl {
urls = [
"https://github.com/ivmai/bdwgc/releases/download/v${finalAttrs.version}/gc-${finalAttrs.version}.tar.gz"
];
sha256 = "sha256-PQ082+B3QD0xBrtA8Mu1Y0E9bv27Kn4c1ohlld7Ej8I=";
};
nativeBuildInputs = [ cmake ninja ];
buildInputs = [ libatomic_ops ];
#outputs = [ "out" "dev" "doc" ];
ninjaFlags = [ "-v" ];
cmakeFlags = [
#"-Denable_cplusplus=ON"
"-Ddefault_enable_threads=ON"
"-DBUILD_SHARED_LIBS=OFF"
"-Denable_threads=ON"
"-Denable_parallel_mark=ON"
"-Denable_thread_local_alloc=ON"
"-Denable_mmap=ON"
# TODO: Do we want to return the pages to the OS if empty for N collections?
"-Denable_munmap=ON"
"-Denable_werror=ON"
# TODO: Do we want the entire GC in a single object file?
"-Denable_single_obj_compilation=ON"
"-Dwith_libatomic_ops=OFF"
"-Dwithout_libatomic_ops=ON"
"-DCMAKE_INSTALL_LIBDIR=${placeholder "out"}/lib"
];
# `gctest` fails under emulation on aarch64-darwin
doCheck = !(stdenv.isDarwin && stdenv.isx86_64);
enableParallelBuilding = true;
passthru.tests = nixVersions;
meta = with lib; {
homepage = "https://hboehm.info/gc/";
description = "The Boehm-Demers-Weiser conservative garbage collector for C and C++";
longDescription = ''
The Boehm-Demers-Weiser conservative garbage collector can be used as a
garbage collecting replacement for C malloc or C++ new. It allows you
to allocate memory basically as you normally would, without explicitly
deallocating memory that is no longer useful. The collector
automatically recycles memory when it determines that it can no longer
be otherwise accessed.
The collector is also used by a number of programming language
implementations that either use C as intermediate code, want to
facilitate easier interoperation with C libraries, or just prefer the
simple collector interface.
Alternatively, the garbage collector may be used as a leak detector for
C or C++ programs, though that is not its primary goal.
'';
# non-copyleft, X11-style license
changelog = "https://github.com/ivmai/bdwgc/blob/v${finalAttrs.version}/ChangeLog";
license = "https://hboehm.info/gc/license.txt";
maintainers = with maintainers; [ AndersonTorres ];
platforms = platforms.all;
};
})

View File

@ -1,111 +0,0 @@
# Serene Programming Language
#
# Copyright (c) 2019-2024 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, version 2.
#
# 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/>.
{ ... }:
with builtins;
let getEnv = p: (p.env or { }).NIX_LDFLAGS or p.NIX_LDFLAGS or "";
in {
# Most of these overlays are do to bugs and problems
# in upstream nixpkgs. But thanks to their design
# We can fix them using these overlays and contribute
# them upstream little by little.
sereneDev = (final: prev:
if !prev.stdenv.hostPlatform.isLinux then
prev
else {
p11-kit = prev.p11-kit.overrideAttrs
(old: { patches = [ ./nix/patches/p11-kit_skip_test.patch ]; });
cpio = prev.cpio.overrideAttrs (old: {
nativeBuildInputs = [ final.autoreconfHook ];
NIX_CFLAGS_COMPILE = "-Wno-implicit-function-declaration";
});
libedit = prev.libedit.overrideAttrs (old: {
# Musl is ISO 10646 compliant but doesn't define __STDC_ISO_10646__ we need to do it ourselves
NIX_CFLAGS_COMPILE = "-D__STDC_ISO_10646__=201103L";
});
elfutils = prev.elfutils.overrideAttrs (old: {
# libcxx does not have __cxa_demangle
configureFlags = old.configureFlags ++ [ "--disable-demangler" ];
});
ccache = prev.ccache.overrideAttrs (old: {
nativeBuildInputs = old.nativeBuildInputs ++ [ final.elfutils ];
});
# We don't need systemd at all
util-linux = prev.util-linux.override { systemdSupport = false; };
# libpam exmaples use glibc. We need to disable them
linux-pam = prev.linux-pam.overrideAttrs (old: {
postConfigure = ''
sed 's/examples//' -i Makefile
'';
});
#=============================================================
# Since we're using lld-18, and --no-undefined-version is the
# default in lld-18. We need to explicitly turn it off for
# these problematic packages untill they fix it upstream.
libxcrypt = prev.libxcrypt.overrideAttrs (old: {
env.NIX_LDFLAGS = "${getEnv old} --undefined-version";
#old.NIX_FLAGS ++ final.lib.optional (prev.stdenv.cc.isClang)
});
ncurses = prev.ncurses.overrideAttrs
(old: { env.NIX_LDFLAGS = "${getEnv old} --undefined-version"; });
libbsd = prev.libbsd.overrideAttrs (old: {
env.NIX_LDFLAGS = "${getEnv old} --undefined-version";
# NIX_LDFLAGS = [ ] ++ final.lib.optional (prev.stdenv.cc.isClang)
# [ "--undefined-version" ];
});
libxml2 = prev.libxml2.overrideAttrs (old: {
env.NIX_LDFLAGS = "${getEnv old} --undefined-version";
propagatedBuildInputs = old.propagatedBuildInputs
++ [ final.zlib.static ];
# NIX_LDFLAGS = [ ] ++ final.lib.optional (prev.stdenv.cc.isClang)
# [ "--undefined-version" ];
});
# binutils = prev.binutils.overrideAttrs (old: {
# env.NIX_LDFLAGS = (getEnv old NIX_LDFLAGS " ") ++ "--undefined-version";
# buildInputs = [ final.zlib final.gettext final.zlib.static ];
# });
});
iwyu = (final: prev: {
iwyu = (prev.include-what-you-use.overrideAttrs (old:
let version = "0.22";
in {
inherit version;
src = prev.fetchurl {
url =
"${old.meta.homepage}/downloads/${old.pname}-${version}.src.tar.gz";
hash = "sha256-hZB0tGHqS4MlpzQYwgfKM7XmVmsI5rWH65FkQWVppt0=";
};
cmakeFlags = [ "-DCMAKE_PREFIX_PATH=${prev.llvmPackages_18.llvm.dev}" ];
})).override { llvmPackages = prev.__splicedPackages.llvmPackages_18; };
});
}

View File

@ -1,27 +0,0 @@
From 132b779414c2236c1350b578b59c8edcfc4c5a14 Mon Sep 17 00:00:00 2001
From: Sameer Rahmani <lxsameer@gnu.org>
Date: Sat, 25 Nov 2023 13:14:42 +0000
Subject: [PATCH] test
---
common/test.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/common/test.c b/common/test.c
index 6cdbd1fa2118..6cd6f84bcdc7 100644
--- a/common/test.c
+++ b/common/test.c
@@ -614,8 +614,9 @@ p11_test_copy_setgid (const char *input,
assert (fd >= 0);
copy_file (input, fd);
- if (fchown (fd, getuid (), group) < 0)
- assert_not_reached ();
+ if (fchown (fd, getuid (), group) < 0) {
+ return NULL;
+ }
if (fchmod (fd, 02750) < 0)
assert_not_reached ();
if (close (fd) < 0)
--
2.41.0

View File

@ -1,29 +0,0 @@
# Serene Programming Language
#
# Copyright (c) 2019-2024 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, version 2.
#
# 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/>.
{ nixpkgs }: {
getPkgs = system: overlays:
if system == "x86_64-linux" then
import nixpkgs {
inherit system overlays;
linker = "lld";
crossSystem = nixpkgs.lib.systems.examples.musl64 // {
useLLVM = true;
};
}
else
import nixpkgs { inherit system overlays; };
}

View File

@ -1,69 +0,0 @@
FROM docker.io/debian:sid-slim
ARG VERSION
RUN apt-get update && \
apt-get install --no-install-recommends -y \
gnupg \
cmake \
ccache \
git \
ninja-build \
binutils \
lsb-release \
wget \
software-properties-common \
zlib1g \
cppcheck \
shellcheck \
zlib1g-dev
RUN wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh
RUN ./llvm.sh ${VERSION} all
RUN apt-get update --fix-missing && \
apt-get install -y --no-install-recommends \
mlir-${VERSION}-tools \
libmlir-${VERSION}-dev \
libmlir-${VERSION} \
libmlir-${VERSION}-dbgsym \
liblld-${VERSION} \
liblld-${VERSION}-dev \
clang-format-${VERSION} \
clang-tidy-${VERSION}
RUN ln -s `which lld-${VERSION}` /usr/bin/lld && \
ln -s `which clang-${VERSION}` /usr/bin/clang && \
ln -s `which clang++-${VERSION}` /usr/bin/clang++ && \
ln -s `which clang-format-${VERSION}` /usr/bin/clang-format && \
ln -s `which clang-tidy-${VERSION}` /usr/bin/clang-tidy && \
ln -s `which mlir-tblgen-${VERSION}` /usr/bin/mlir-tblgen
ENV MLIR_DIR /usr/lib/llvm-${VERSION}
ENV CMAKE_PREFIX_PATH=/usr/lib/llvm-${VERSION}
ENV LD_LIBRARY_PATH=/usr/lib/llvm-${VERSION}/lib/clang/${VERSION}.0.0/lib/linux/
ENV CC=/usr/bin/clang
ENV CXX=/usr/bin/clang++
# --branch clang_${VERSION}
WORKDIR /iwuy
RUN git clone https://github.com/include-what-you-use/include-what-you-use.git --depth 1 && \
mkdir build && cd build && \
cmake -G Ninja -DCMAKE_PREFIX_PATH=/usr/lib/llvm-${VERSION} ../include-what-you-use && \
cmake --build . && \
cmake -P cmake_install.cmake
WORKDIR /boehm
RUN git clone https://github.com/ivmai/bdwgc.git --depth 1 --branch v8.2.0 && \
mkdir build && cd build && \
cmake -G Ninja -DBUILD_SHARED_LIBS=OFF -Denable_cplusplus=ON -Denable_threads=ON \
-Denable_gcj_support=OFF -Dinstall_headers=ON \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON ../bdwgc && \
cmake --build . --config Release && \
cmake -P cmake_install.cmake
WORKDIR /app
RUN rm /iwuy -rf && rm /boehm -rf && rm /llvm.sh
RUN apt-get purge -y git software-properties-common wget && \
apt-get autoremove -y && \
apt-get clean

View File

@ -1,11 +0,0 @@
FROM rg.fr-par.scw.cloud/serene/llvm:latest
WORKDIR /app
# For CI
COPY .pre-commit-config.yaml .
RUN apt-get update && \
apt-get install -y --no-install-recommends git python3 python3-pip && \
pip3 install pre-commit && \
git init . && \
pre-commit autoupdate && \
rm -fv /app/.pre-commit-config.yaml

View File

@ -1,24 +0,0 @@
FROM debian:sid-slim as builder
RUN apt-get update --fix-missing && apt-get install -y wget gnupg ccache cmake ccache git ninja-build build-essential binutils
RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|apt-key add -
RUN echo "deb http://apt.llvm.org/unstable/ llvm-toolchain main" >> /etc/apt/sources.list
RUN apt-get update --fix-missing && apt-get install -y clang-format-15 clang-tidy-15 clang-tools-15 clang-15 clangd-15 libc++-15-dev libc++1-15 libc++abi-15-dev libc++abi1-15 libclang-15-dev libclang1-15 liblldb-15-dev lld-15 lldb-15 llvm-15-dev llvm-15-runtime llvm python3-clang-15 python3-lldb-15 mlir-15-tools libmlir-15-dev
RUN mkdir -p /opt/build
WORKDIR /opt/build
COPY ./ /usr/src/llvm-project
RUN ln -s `which lld-15` /usr/bin/lld && ln -s `which lldb-15` /usr/bin/lldb
RUN cmake -G Ninja /usr/src/llvm-project/llvm -DCMAKE_INSTALL_PREFIX=/opt/llvm -DLLVM_PARALLEL_COMPILE_JOBS=7 -DLLVM_PARALLEL_LINK_JOBS=1 -DLLVM_TARGETS_TO_BUILD="X86" -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_ASSERTIONS=ON -DLLVM_CCACHE_BUILD=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DLLVM_ENABLE_PROJECTS='clang;lldb;lld;mlir;clang-tools-extra;compiler-rt' -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15 -DLLVM_ENABLE_LLD=ON
RUN cmake --build .
RUN cmake -DCMAKE_INSTALL_PREFIX=/opt/llvm -P cmake_install.cmake
FROM debian:sid-slim
COPY --from=builder /opt/llvm /opt/llvm

View File

@ -1,9 +0,0 @@
FROM rg.fr-par.scw.cloud/serene/llvm:15-8
ARG TASK=build
WORKDIR /app
COPY . .
RUN ./builder ${TASK}

View File

@ -1,47 +0,0 @@
FROM alpine:edge
RUN apk update \
&& apk add --no-cache \
ninja \
make \
clang \
clang-dev \
bison \
flex \
# compiler-rt \ #
# llvm-libunwind \
# lld \
gcc \
libgcc
curl \
g++ \
alpine-sdk \
libatomic \
libgcc \
cmake \
bash \
git \
linux-headers \
zlib \
zlib-dev \
zstd \
zstd-dev \
tar \
xz \
python3
# RUN ln -sf /usr/bin/clang /usr/bin/cc \
# && ln -sf /usr/bin/clang++ /usr/bin/c++ \
# && ls -l /usr/bin/cc /usr/bin/c++ \
# && cc --version \
# && c++ --version
# && update-alternatives --install /usr/bin/cc cc /usr/bin/clang 10\
# && update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 10\
RUN addgroup -S serene && \
adduser -h /home/serene -S serene -G serene
USER serene:serene
ENV HOME=/home/serene
WORKDIR /home/serene/serene

View File

@ -1,22 +0,0 @@
FROM alpine:edge
RUN apk update \
&& apk upgrade \
&& apk add --no-cache \
alpine-sdk \
linux-headers \
gcc \
g++ \
libgcc \
build-base \
zlib \
zlib-dev \
zstd \
zstd-dev
# clang-dev \
# compiler-rt \
# libc++-dev \
# llvm-runtimes \
# libc++-static \
# llvm-libunwind \
# lld \

View File

@ -0,0 +1,36 @@
FROM debian:11-slim
RUN apt-get update && apt-get install -y wget gnupg
RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|apt-key add -
RUN echo "deb http://apt.llvm.org/bullseye/ llvm-toolchain-bullseye-13 main" >> /etc/apt/sources.list
RUN apt-get update
RUN apt-get install -y ccache cmake ccache git ninja-build build-essential clang-13 lldb-13 lld-13
ENV CXX=clang++-13
ENV CC=clang-13
RUN mkdir -p /opt/build
COPY ./llvm-project /usr/src/llvm-project
WORKDIR /opt/build
ENV LDFLAGS="-fuse-ld=lld-13"
RUN cmake -G Ninja /usr/src/llvm-project/llvm \
-DCMAKE_INSTALL_PREFIX=/opt/llvm \
-DLLVM_PARALLEL_COMPILE_JOBS=7 \
-DLLVM_PARALLEL_LINK_JOBS=1 \
-DLLVM_BUILD_EXAMPLES=ON \
-DLLVM_TARGETS_TO_BUILD="X86" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_ASSERTIONS=ON \
-DLLVM_CCACHE_BUILD=ON \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DLLVM_ENABLE_PROJECTS='clang;lldb;lld;mlir;clang-tools-extra;compiler-rt' \
-DCMAKE_C_COMPILER=clang-13 \
-DCMAKE_CXX_COMPILER=clang++-13 \
-DLLVM_ENABLE_LLD=ON
RUN cmake --build .
RUN cmake -DCMAKE_INSTALL_PREFIX=/opt/llvm -P cmake_install.cmake

View File

@ -1,6 +1,6 @@
;;; serene-dev --- Serene's development lib for Emacs users -*- lexical-binding: t; -*-
;;
;; Copyright (c) 2019-2024 Sameer Rahmani
;; Copyright (c) 2019-2021 Sameer Rahmani
;;
;; Author: Sameer Rahmani <lxsameer@gnu.org>
;; URL: https://serene-lang.org
@ -35,25 +35,18 @@
(defvar serene/compile-buffer "*compile*")
(defmacro serene/builder (command &optional buf-name sync)
(defmacro serene/builder (command &optional buf-name)
"Run the given COMMAND via the builder script.
Use the optional BUF-NAME as the buffer.
If SYNC is non-nil it will block."
Use the optional BUF-NAME as the buffer."
(let ((buf (or buf-name (format "*%s*" command))))
(if (not sync)
`(projectile-run-async-shell-command-in-root
(format "./builder %s" ,command) ,buf)
`(projectile-run-shell-command-in-root
(format "./builder %s" ,command) ,buf))))
`(projectile-run-async-shell-command-in-root (format "./builder %s" ,command) ,buf)))
(defun serene/compile (&optional sync)
(defun serene/compile ()
"Compile the project.
It will run the `./builder compile' asynchronously or synchronously if
SYNC is non-nil."
It will run the `./builder compile' asynchronously."
(interactive)
(serene/builder "compile" serene/compile-buffer sync))
(serene/builder "compile" serene/compile-buffer))
(defun serene/build ()

View File

@ -1,46 +1,43 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512mm"
height="512mm"
viewBox="0 0 512 512"
version="1.1"
id="svg931"
inkscape:export-filename="serene.png"
inkscape:export-filename="/home/lxsameer/src/serene/serene/resources/images/serene.png"
inkscape:export-xdpi="25.4"
inkscape:export-ydpi="25.4"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
sodipodi:docname="serene.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
inkscape:version="1.0.2 (e86c870879, 2021-01-15)"
sodipodi:docname="serene.svg">
<defs
id="defs925" />
<sodipodi:namedview
id="base"
pagecolor="#000000"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.29845254"
inkscape:cx="170.88144"
inkscape:cy="1060.4701"
inkscape:zoom="0.074613135"
inkscape:cx="-3552.8237"
inkscape:cy="741.94593"
inkscape:document-units="mm"
inkscape:current-layer="g1039"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1063"
inkscape:window-height="1064"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1" />
inkscape:window-maximized="0" />
<metadata
id="metadata928">
<rdf:RDF>
@ -49,6 +46,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
@ -56,25 +54,28 @@
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#ffffff;stroke-width:32.4311;stroke-linejoin:round"
id="rect1506"
width="512"
height="512"
x="0"
y="1.8041124e-14" />
<g
id="g1039"
transform="matrix(5.4643699,0,0,5.4643699,-646.86584,-18.784791)">
<path
id="path293"
style="clip-rule:evenodd;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.0676825;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;image-rendering:optimizeQuality;shape-rendering:geometricPrecision;text-rendering:geometricPrecision"
d="m 165.1472,4.0209328 c -1.69431,0 -3.25301,0.4054703 -4.67634,1.2165468 L 127.87228,24.027579 c -1.55881,0.743535 -2.84653,1.893108 -3.79538,3.380092 -1.01663,1.486995 -1.49162,3.24371 -1.49162,5.068664 v 35.6206 c 0,1.824974 0.47447,3.581711 1.49162,5.068684 0.94894,1.486995 2.23657,2.63658 3.79538,3.380083 l 32.59858,18.790093 c 1.42333,0.811046 2.98203,1.216548 4.67634,1.216548 0.0302,0 0.0503,-0.0032 0.0806,-0.0032 0.0302,2.32e-4 0.0604,0.0032 0.0806,0.0032 1.6943,0 3.25302,-0.40547 4.67633,-1.216548 l 32.5986,-18.790093 c 1.55881,-0.743535 2.84655,-1.893088 3.79538,-3.380083 1.01665,-1.486973 1.49162,-3.24371 1.49162,-5.068684 v -35.6206 c 0,-1.824954 -0.47547,-3.581669 -1.49162,-5.068664 -0.94894,-1.486984 -2.23657,-2.6366 -3.79538,-3.380092 L 169.98472,5.2374796 c -1.42332,-0.8111397 -2.98203,-1.2165468 -4.67634,-1.2165468 -0.0302,0 -0.0604,0.00316 -0.0806,0.00316 -0.0302,-1.475e-4 -0.0503,-0.00316 -0.0806,-0.00316 z m 0,7.4347692 c 0.0302,0 0.0604,0.01106 0.0806,0.01106 0.0302,-0.0011 0.0604,-0.01106 0.0806,-0.01106 0.33847,0 0.67695,0.06826 0.94794,0.271142 l 32.73594,18.857089 0.26998,0.06826 v 0.06731 c 0.33848,0.135118 0.67797,0.40567 0.88045,0.676023 0.20348,0.337959 0.27199,0.675517 0.27199,1.08104 v 35.620589 c 0,0.405576 -0.0705,0.743134 -0.27199,1.081061 -0.20349,0.270247 -0.54197,0.540905 -0.88045,0.676023 v 0.06826 l -0.26998,0.134011 -32.73594,18.858585 c -0.27099,0.135129 -0.60947,0.202535 -0.94794,0.202535 -0.0302,0 -0.0604,-0.0084 -0.0806,-0.0084 -0.0302,0 -0.0604,0.0084 -0.0806,0.0084 -0.33848,0 -0.67696,-0.06731 -0.94794,-0.202535 L 131.46337,70.05651 131.1934,69.922499 v -0.06826 c -0.33848,-0.135118 -0.67796,-0.405776 -0.88045,-0.676023 -0.20348,-0.337958 -0.27199,-0.675517 -0.27199,-1.081061 V 32.47643 c 0,-0.405565 0.0705,-0.743123 0.27199,-1.081029 0.2035,-0.270353 0.54197,-0.540895 0.88045,-0.676023 v -0.06732 l 0.26997,-0.06826 32.73589,-18.857121 c 0.27098,-0.202841 0.60946,-0.271152 0.94794,-0.271152 z" />
<path
id="path1019"
style="clip-rule:evenodd;fill:#5e246d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.0608809;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;image-rendering:optimizeQuality;shape-rendering:geometricPrecision;text-rendering:geometricPrecision"
d="m 165.1553,8.6703245 c -1.52405,0 -2.92581,0.364799 -4.2061,1.094368 L 131.62653,26.666424 c -1.40216,0.668814 -2.56034,1.702681 -3.41384,3.040234 -0.91447,1.337561 -1.34213,2.918061 -1.34213,4.559619 v 32.040724 c 0,1.641575 0.4272,3.221583 1.34213,4.559126 0.85358,1.337564 2.01168,2.37194 3.41384,3.040727 l 29.32267,16.901731 c 1.28029,0.729541 2.68205,1.094366 4.2061,1.094366 0.0272,0 0.0453,-0.0029 0.0725,-0.0029 0.0272,2.1e-4 0.0544,0.0029 0.0725,0.0029 1.52404,0 2.9263,-0.364797 4.20658,-1.094366 l 29.32268,-16.901731 c 1.40215,-0.668814 2.56034,-1.703163 3.41383,-3.040727 0.91448,-1.337543 1.34165,-2.917551 1.34165,-4.559126 V 34.266277 c 0,-1.641558 -0.42761,-3.222058 -1.34165,-4.559619 -0.85357,-1.337553 -2.01168,-2.37146 -3.41383,-3.040234 L 169.50681,9.7646925 c -1.28028,-0.729626 -2.68254,-1.094368 -4.20658,-1.094368 -0.0272,0 -0.0544,0.0029 -0.0725,0.0029 -0.0272,-1.33e-4 -0.0453,-0.0029 -0.0725,-0.0029 z" />
style="clip-rule:evenodd;fill:#5e246d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.0642522;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;image-rendering:optimizeQuality;shape-rendering:geometricPrecision;text-rendering:geometricPrecision"
d="m 165.15124,6.3658643 c -1.60844,0 -3.08783,0.3850005 -4.43901,1.1549697 L 129.7658,25.358505 c -1.4798,0.70585 -2.70212,1.796968 -3.60288,3.208589 -0.96511,1.411629 -1.41645,3.079649 -1.41645,4.812109 v 33.814991 c 0,1.732478 0.45086,3.39998 1.41645,4.81159 0.90085,1.411632 2.12308,2.503287 3.60288,3.209108 l 30.94643,17.837671 c 1.35118,0.76994 2.83057,1.154967 4.43901,1.154967 0.0287,0 0.0478,-0.0031 0.0765,-0.0031 0.0287,2.22e-4 0.0574,0.0031 0.0765,0.0031 1.60843,0 3.08834,-0.384998 4.43952,-1.154967 L 200.6902,75.214892 c 1.47979,-0.70585 2.70212,-1.797476 3.60287,-3.209108 0.96512,-1.41161 1.41594,-3.079112 1.41594,-4.81159 V 33.379203 c 0,-1.73246 -0.45129,-3.40048 -1.41594,-4.812109 -0.90084,-1.411621 -2.12308,-2.502781 -3.60287,-3.208589 L 169.74372,7.520834 c -1.35118,-0.7700301 -2.83109,-1.1549697 -4.43952,-1.1549697 -0.0287,0 -0.0574,0.0031 -0.0765,0.0031 -0.0287,-1.402e-4 -0.0478,-0.0031 -0.0765,-0.0031 z" />
<path
id="path1052"
style="clip-rule:evenodd;fill:#8800aa;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.0608809;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;image-rendering:optimizeQuality;shape-rendering:geometricPrecision;text-rendering:geometricPrecision"
d="m 165.15533,8.670325 c -1.52405,0 -2.92612,0.364723 -4.2064,1.094292 l -29.32265,16.901821 c -1.40215,0.668814 -2.56047,1.702863 -3.41397,3.040416 -0.91447,1.337562 -1.34172,2.917739 -1.34172,4.559297 V 66.30712 c 0,1.641577 0.4268,3.221773 1.34172,4.559316 0.85358,1.337562 2.01182,2.371621 3.41397,3.040407 l 29.32265,16.901815 c 1.28028,0.729542 2.68235,1.094293 4.2064,1.094293 0.0272,0 0.0453,-0.0028 0.0725,-0.0028 0.0272,2.08e-4 0.0544,0.0028 0.0725,0.0028 1.52404,0 2.92611,-0.364723 4.20639,-1.094293 l 29.32261,-16.901815 c 1.40215,-0.668815 2.56048,-1.702845 3.41397,-3.040407 0.91448,-1.337543 1.34172,-2.917739 1.34172,-4.559316 V 34.266151 c 0,-1.641558 -0.42769,-3.221735 -1.34172,-4.559297 -0.85358,-1.337553 -2.01182,-2.37164 -3.41397,-3.040416 L 169.50673,9.764617 c -1.28028,-0.729626 -2.68235,-1.094292 -4.20639,-1.094292 -0.0272,0 -0.0544,0.0028 -0.0725,0.0028 -0.0272,-1.32e-4 -0.0453,-0.0028 -0.0725,-0.0028 z m 0,6.687625 c 0.0272,0 0.0544,0.0099 0.0725,0.0099 0.0272,-9.48e-4 0.0544,-0.0099 0.0725,-0.0099 0.30446,0 0.60892,0.0614 0.85267,0.243894 l 29.44621,16.962079 0.24284,0.0614 v 0.06055 c 0.30447,0.121539 0.60984,0.364903 0.79198,0.608087 0.18303,0.303996 0.24465,0.607632 0.24465,0.972402 v 32.04096 c 0,0.364818 -0.0634,0.668454 -0.24465,0.972422 -0.18305,0.243089 -0.48751,0.486547 -0.79198,0.608087 v 0.0614 L 195.59921,68.069776 166.153,85.0332 c -0.24375,0.121549 -0.54821,0.182181 -0.85267,0.182181 -0.0272,0 -0.0544,-0.0076 -0.0725,-0.0076 -0.0272,0 -0.0544,0.0076 -0.0725,0.0076 -0.30447,0 -0.60893,-0.06055 -0.85268,-0.182181 L 134.8565,68.069776 134.61366,67.949231 v -0.0614 c -0.30447,-0.12154 -0.60984,-0.364998 -0.79198,-0.608087 -0.18303,-0.303996 -0.24465,-0.607632 -0.24465,-0.972422 V 34.266236 c 0,-0.364808 0.0634,-0.668444 0.24465,-0.972393 0.18305,-0.243184 0.48751,-0.486538 0.79198,-0.608087 v -0.06055 l 0.24284,-0.0614 29.44615,-16.962107 c 0.24375,-0.182456 0.54821,-0.243904 0.85268,-0.243904 z" />
style="clip-rule:evenodd;fill:#8800aa;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.0642522;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;image-rendering:optimizeQuality;shape-rendering:geometricPrecision;text-rendering:geometricPrecision"
d="m 165.15142,6.365746 c -1.60844,0 -3.08815,0.38492 -4.43933,1.154889 l -30.9464,17.837766 c -1.4798,0.70585 -2.70226,1.79716 -3.60302,3.20878 -0.96511,1.41163 -1.41602,3.07931 -1.41602,4.81177 v 33.81525 c 0,1.73248 0.45043,3.40018 1.41602,4.81179 0.90085,1.41163 2.12322,2.50295 3.60302,3.20877 l 30.9464,17.83776 c 1.35118,0.76994 2.83089,1.15489 4.43933,1.15489 0.0287,0 0.0478,-0.003 0.0765,-0.003 0.0287,2.2e-4 0.0574,0.003 0.0765,0.003 1.60843,0 3.08814,-0.38492 4.43932,-1.15489 l 30.94636,-17.83776 c 1.4798,-0.70585 2.70227,-1.79714 3.60302,-3.20877 0.96512,-1.41161 1.41602,-3.07931 1.41602,-4.81179 v -33.81525 c 0,-1.73246 -0.45138,-3.40014 -1.41602,-4.81177 -0.90085,-1.41162 -2.12322,-2.50297 -3.60302,-3.20878 L 169.74375,7.520635 c -1.35118,-0.770029 -2.83089,-1.154889 -4.43932,-1.154889 -0.0287,0 -0.0574,0.003 -0.0765,0.003 -0.0287,-1.4e-4 -0.0478,-0.003 -0.0765,-0.003 z m 0,7.057955 c 0.0287,0 0.0574,0.0105 0.0765,0.0105 0.0287,-10e-4 0.0574,-0.0105 0.0765,-0.0105 0.32132,0 0.64264,0.0648 0.89989,0.2574 l 31.0768,17.90136 0.25629,0.0648 v 0.0639 c 0.32133,0.12827 0.64361,0.38511 0.83583,0.64176 0.19317,0.32083 0.2582,0.64128 0.2582,1.02625 v 33.81524 c 0,0.38502 -0.0669,0.70547 -0.2582,1.02627 -0.19318,0.25655 -0.5145,0.51349 -0.83583,0.64176 v 0.0648 l -0.25629,0.12722 -31.0768,17.90278 c -0.25725,0.12828 -0.57857,0.19227 -0.89989,0.19227 -0.0287,0 -0.0574,-0.008 -0.0765,-0.008 -0.0287,0 -0.0574,0.008 -0.0765,0.008 -0.32133,0 -0.64265,-0.0639 -0.8999,-0.19227 l -31.07674,-17.90278 -0.25629,-0.12722 v -0.0648 c -0.32133,-0.12827 -0.64361,-0.38521 -0.83583,-0.64176 -0.19317,-0.32083 -0.2582,-0.64128 -0.2582,-1.02627 v -33.81537 c 0,-0.38501 0.0669,-0.70546 0.2582,-1.02624 0.19318,-0.25665 0.5145,-0.51348 0.83583,-0.64176 v -0.0639 l 0.25629,-0.0648 31.07674,-17.90139 c 0.25725,-0.19256 0.57857,-0.25741 0.8999,-0.25741 z" />
<path
id="path1050"
style="clip-rule:evenodd;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.41896;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;image-rendering:optimizeQuality;shape-rendering:geometricPrecision;text-rendering:geometricPrecision"
d="m 165.17999,20.897696 c -1.07631,0 -2.06645,0.257548 -2.9705,0.772834 l -20.70721,11.93581 c -0.99023,0.472268 -1.8082,1.202568 -2.41097,2.147113 -0.64608,0.944583 -0.9475,2.060499 -0.9475,3.219727 v 3.633996 h 4.73462 v 0.0163 c 6.8149,-0.117304 21.45623,-0.03705 21.98758,0.42094 0.63431,0.547085 0.88168,1.721805 1.21596,3.772099 0.009,0.08405 -0.009,0.175141 -0.0634,0.254469 -0.20117,0.296596 -0.41955,0.585687 -0.63068,0.875849 -1.43759,1.978472 -2.91387,3.896301 -4.65022,5.726257 -1.56119,1.64223 -3.31765,3.199013 -5.3842,4.613912 -2.3275,1.594324 -5.04746,3.006097 -8.26853,4.121131 -0.0544,0.0216 -0.10692,0.04245 -0.15766,0.0687 0.0453,0.01895 0.0634,0.02985 0.0816,0.038 3.31692,1.018387 5.58871,1.336814 7.53438,0.906142 1.92437,-0.42599 4.15057,-1.738557 6.8544,-4.417186 3.6135,-3.105379 4.80762,-5.200093 5.60901,-5.773539 0.82096,-0.587478 0.98071,0.319811 1.48526,2.772322 0.1486,0.691138 0.34886,1.609342 0.61979,2.571786 0.0816,0.289992 0.17036,0.592823 0.27003,0.905195 0.6198,1.762624 1.25292,3.04215 1.93199,3.867638 0.68322,0.830387 1.43677,1.234812 2.39574,1.246656 1.39717,0.018 8.63198,-2.82147 13.87373,-5.602348 v 2.608683 c 0,0.257643 -0.0453,0.471993 -0.17217,0.686713 -0.12957,0.171702 -0.34433,0.343584 -0.55999,0.42943 v 0.0434 l -0.17216,0.08499 -20.79447,11.979349 c -0.17217,0.08585 -0.38693,0.128589 -0.60258,0.128589 -0.0181,0 -0.0363,-0.0057 -0.0544,-0.0057 -0.0181,0 -0.0362,0.0057 -0.0544,0.0057 -0.21567,0 -0.43043,-0.04245 -0.60259,-0.128589 l -20.79447,-11.979349 -0.17217,-0.08499 v -0.0434 c -0.21475,-0.08585 -0.43041,-0.257728 -0.55999,-0.42943 -0.12957,-0.214625 -0.17216,-0.42907 -0.17216,-0.686713 V 48.480119 h -4.73562 v 13.120052 c 0,1.159265 0.30174,2.275172 0.94759,3.219727 0.60258,0.944564 1.42074,1.674816 2.41088,2.147103 l 20.70729,11.935838 c 0.90433,0.515191 1.8942,0.77274 2.97051,0.77274 0.0181,0 0.0363,-0.0019 0.0544,-0.0019 0.0181,1.42e-4 0.0363,0.0019 0.0544,0.0019 1.07622,0 2.06645,-0.257549 2.9705,-0.77274 l 20.7072,-11.935838 c 0.99023,-0.472268 1.8082,-1.202539 2.41097,-2.147113 0.64608,-0.944555 0.94746,-2.060461 0.94746,-3.219717 v -9.607122 l -4.70903,2.131015 c -0.003,0.0019 -0.007,0.0028 -0.009,0.0038 l -0.0181,0.0085 v 9.38e-4 c -3.48484,1.756371 -11.14498,4.995067 -11.61364,4.952542 -0.48841,-0.04434 -0.97229,-0.86085 -1.83811,-2.850834 -1.36047,-3.088617 -1.92382,-6.659801 -2.61575,-9.97412 -0.10602,-0.505431 -0.20116,-0.997673 -0.28996,-1.462304 -0.18938,-0.967172 -0.35611,-1.848631 -0.54188,-2.632334 -0.4576,-1.990419 -1.04505,-3.389012 -2.60913,-4.059636 -0.78019,-0.334535 -7.12363,-0.491692 -13.78929,-0.447414 -3.89132,0.02615 -7.80693,0.126609 -10.86815,0.294151 0.0634,-0.03885 0.12596,-0.07504 0.19029,-0.10022 v -0.04245 l 0.17126,-0.0434 20.79447,-11.978402 c 0.17217,-0.128864 0.38692,-0.172062 0.60258,-0.172062 0.0181,0 0.0363,0.0076 0.0544,0.0076 0.0181,-9.38e-4 0.0363,-0.0076 0.0544,-0.0076 0.21566,0 0.43041,0.0434 0.60258,0.172062 l 20.79455,11.978402 0.17127,0.0434 v 0.04245 c 0.21566,0.08585 0.43041,0.257643 0.55999,0.42943 0.12958,0.21472 0.17308,0.42907 0.17308,0.686713 v 8.600731 l 4.73549,-2.046854 v -6.553877 c 0,-1.159256 -0.30175,-2.275152 -0.94747,-3.219726 -0.60258,-0.944555 -1.42073,-1.674807 -2.41096,-2.147094 l -20.7073,-11.935801 c -0.90433,-0.515191 -1.89419,-0.772739 -2.9705,-0.772739 -0.0181,0 -0.0363,0.0028 -0.0544,0.0028 -0.0181,-9.5e-5 -0.0363,-0.0028 -0.0544,-0.0028 z" />
style="clip-rule:evenodd;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.49754;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;image-rendering:optimizeQuality;shape-rendering:geometricPrecision;text-rendering:geometricPrecision"
d="m 165.17475,19.270251 c -1.13592,0 -2.18088,0.27181 -3.135,0.81563 l -21.85388,12.59676 c -1.04506,0.49842 -1.90833,1.26916 -2.54448,2.26601 -0.68185,0.99689 -0.99996,2.1746 -0.99996,3.39802 v 3.83523 h 4.9968 v 0.0172 c 7.19228,-0.1238 22.64437,-0.0391 23.20515,0.44425 0.66943,0.57738 0.9305,1.81715 1.28329,3.98098 0.01,0.0887 -0.01,0.18484 -0.0669,0.26856 -0.21231,0.31302 -0.44278,0.61812 -0.6656,0.92435 -1.5172,2.08803 -3.07523,4.11206 -4.90773,6.04335 -1.64764,1.73317 -3.50137,3.37616 -5.68235,4.86941 -2.45639,1.68261 -5.32697,3.17256 -8.7264,4.34934 -0.0574,0.0228 -0.11284,0.0448 -0.1664,0.0725 0.0478,0.02 0.0669,0.0315 0.0861,0.0401 3.5006,1.07478 5.89819,1.41084 7.9516,0.95632 2.03093,-0.44958 4.38041,-1.83483 7.23397,-4.66179 3.8136,-3.27734 5.07384,-5.48805 5.91961,-6.09325 0.86642,-0.62001 1.03502,0.33752 1.5675,2.92584 0.15683,0.72941 0.36818,1.69846 0.65412,2.7142 0.0861,0.30605 0.17979,0.62565 0.28498,0.95532 0.65412,1.86023 1.3223,3.21061 2.03897,4.08181 0.72106,0.87637 1.51634,1.30319 2.52841,1.31569 1.47454,0.019 9.10998,-2.97771 14.64199,-5.91258 v 2.75314 c 0,0.27191 -0.0478,0.49813 -0.1817,0.72474 -0.13675,0.18121 -0.3634,0.36261 -0.591,0.45321 v 0.0458 l -0.1817,0.0897 -21.94597,12.64271 c -0.1817,0.0906 -0.40835,0.13571 -0.63595,0.13571 -0.0191,0 -0.0383,-0.006 -0.0574,-0.006 -0.0191,0 -0.0382,0.006 -0.0574,0.006 -0.22761,0 -0.45426,-0.0448 -0.63596,-0.13571 l -21.94597,-12.64271 -0.1817,-0.0897 v -0.0458 c -0.22664,-0.0906 -0.45425,-0.272 -0.591,-0.45321 -0.13675,-0.22651 -0.1817,-0.45283 -0.1817,-0.72474 v -13.84658 h -4.99785 v 13.84658 c 0,1.22346 0.31845,2.40116 1.00006,3.39802 0.63595,0.99687 1.49941,1.76756 2.54438,2.266 l 21.85397,12.59679 c 0.95441,0.54372 1.99909,0.81553 3.135,0.81553 0.0191,0 0.0383,-0.002 0.0574,-0.002 0.0191,1.5e-4 0.0383,0.002 0.0574,0.002 1.13582,0 2.18088,-0.27181 3.135,-0.81553 l 21.85388,-12.59679 c 1.04506,-0.49842 1.90833,-1.26913 2.54447,-2.26601 0.68186,-0.99686 0.99993,-2.17456 0.99993,-3.39801 v -10.13912 l -4.96979,2.24902 c -0.003,0.002 -0.007,0.003 -0.009,0.004 l -0.0191,0.009 v 9.9e-4 c -3.67781,1.85363 -11.76214,5.27167 -12.25675,5.22679 -0.51545,-0.0468 -1.02613,-0.90852 -1.93989,-3.0087 -1.43581,-3.25965 -2.03036,-7.02859 -2.7606,-10.52644 -0.11189,-0.53342 -0.2123,-1.05292 -0.30602,-1.54328 -0.19987,-1.02073 -0.37583,-1.951 -0.57188,-2.7781 -0.48294,-2.10064 -1.10292,-3.57668 -2.75362,-4.28444 -0.82339,-0.35306 -7.5181,-0.51892 -14.55287,-0.47219 -4.10681,0.0276 -8.23925,0.13362 -11.46998,0.31044 0.0669,-0.041 0.13293,-0.0792 0.20083,-0.10577 v -0.0448 l 0.18074,-0.0458 21.94597,-12.64171 c 0.1817,-0.136 0.40835,-0.18159 0.63595,-0.18159 0.0191,0 0.0383,0.008 0.0574,0.008 0.0191,-9.9e-4 0.0383,-0.008 0.0574,-0.008 0.2276,0 0.45425,0.0458 0.63595,0.18159 l 21.94606,12.64171 0.18075,0.0458 v 0.0448 c 0.2276,0.0906 0.45425,0.27191 0.591,0.45321 0.13676,0.22661 0.18266,0.45283 0.18266,0.72474 v 9.077 l 4.99772,-2.1602 v -6.9168 c 0,-1.22345 -0.31846,-2.40114 -0.99993,-3.39802 -0.63595,-0.99686 -1.49941,-1.76755 -2.54447,-2.26599 l -21.85397,-12.59675 c -0.95441,-0.54372 -1.99909,-0.81553 -3.135,-0.81553 -0.0191,0 -0.0383,0.003 -0.0574,0.003 -0.0191,-10e-5 -0.0383,-0.003 -0.0574,-0.003 z" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@ -1 +0,0 @@
Here is a list of all the generous people who has supported Serene so far:

View File

@ -1,101 +0,0 @@
#! /bin/zsh
# shellcheck disable=all
# Serene Programming Language
#
# Copyright (c) 2019-2024 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, version 2.
#
# 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/>.
mkdir -p "$HOME/.config/serene/"
export HISTFILE="$HOME/.config/serene/.zsh_history"
export HISTFILESIZE=500
export SAVEHIST=500
export HISTSIZE=500
setopt HIST_IGNORE_DUPS
setopt NO_HIST_BEEP
setopt PROMPT_SUBST
setopt NO_BEEP
setopt AUTO_CD
setopt CORRECT
setopt SHARE_HISTORY
setopt HIST_IGNORE_ALL_DUPS
setopt NO_ERR_EXIT
function user_prompt () {
if [ $UID != 0 ]; then
echo "%F{028}%F{002}> "
else
echo "%F{001}# "
fi
}
autoload -U colors && colors
autoload -Uz compinit
compinit
zstyle ':completion:*' auto-description 'specify: %d'
zstyle ':completion:*' completer _expand _complete _correct _approximate
zstyle ':completion:*' format 'Completing %d'
zstyle ':completion:*' group-name ''
if [ "$(uname 2> /dev/null)" = "Linux" ]; then
zstyle ':completion:*' menu select=2 eval "$(dircolors -b)"
fi
zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS}
zstyle ':completion:*' list-colors ''
zstyle ':completion:*' list-prompt %SAt %p: Hit TAB for more, or the character to insert%s
zstyle ':completion:*' matcher-list '' 'm:{a-z}={A-Z}' 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=* l:|=*'
zstyle ':completion:*' menu select=long
zstyle ':completion:*' select-prompt %SScrolling active: current selection at %p%s
zstyle ':completion:*' use-compctl false
zstyle ':completion:*' verbose true
zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#)*=0=01;31'
zstyle ':completion:*:kill:*' command 'ps -u $USER -o pid,%cpu,tty,cputime,cmd'
echo "Welcome to serene's development environment"
PROMPT='
%F{015}[%F{099}${BUILDER:-SERENE}%F{015}][%F{198}$(git branch --show-current)%F{015}]
%F{005}%~%F{003} $(user_prompt)%f'
echo -e "\nSerene Development Shell $VERSION"
echo -e "\nCopyright (C) 2019-2024"
echo -e "Sameer Rahmani <lxsameer@gnu.org>"
echo -e "Serene comes with ABSOLUTELY NO WARRANTY;"
echo -e "This is free software, and you are welcome"
echo -e "to redistribute it under certain conditions;"
echo -e "for details take a look at the LICENSE file.\n"
echo -e "\nUse the 'help' command to view a list of helpers.\n"
ME=$(cd "$(dirname "$0")/." >/dev/null 2>&1 ; pwd -P)
export ME
BUILD_DIR_NAME="build"
export BUILD_DIR_NAME
BUILD_DIR="$ME/$BUILD_DIR_NAME"
export BUILD_DIR
SERENE_HOME_DIR="$HOME/.serene"
export SERENE_HOME_DIR
VERSION="0.9.0"
builder="${BUILDER:l}"
. "$ME/scripts/${builder}functions.sh"
export PROMPT

342
scripts/apply-format Executable file
View File

@ -0,0 +1,342 @@
#! /bin/bash
#
# Copyright 2018 Undo Ltd.
#
# https://github.com/barisione/clang-format-hooks
# Force variable declaration before access.
set -u
# Make any failure in piped commands be reflected in the exit code.
set -o pipefail
readonly bash_source="${BASH_SOURCE[0]:-$0}"
##################
# Misc functions #
##################
function error_exit() {
for str in "$@"; do
echo -n "$str" >&2
done
echo >&2
exit 1
}
########################
# Command line parsing #
########################
function show_help() {
if [ -t 1 ] && hash tput 2> /dev/null; then
local -r b=$(tput bold)
local -r i=$(tput sitm)
local -r n=$(tput sgr0)
else
local -r b=
local -r i=
local -r n=
fi
cat << EOF
${b}SYNOPSIS${n}
To reformat git diffs:
${i}$bash_source [OPTIONS] [FILES-OR-GIT-DIFF-OPTIONS]${n}
To reformat whole files, including unchanged parts:
${i}$bash_source [-f | --whole-file] FILES${n}
${b}DESCRIPTION${n}
Reformat C or C++ code to match a specified formatting style.
This command can either work on diffs, to reformat only changed parts of
the code, or on whole files (if -f or --whole-file is used).
${b}FILES-OR-GIT-DIFF-OPTIONS${n}
List of files to consider when applying clang-format to a diff. This is
passed to "git diff" as is, so it can also include extra git options or
revisions.
For example, to apply clang-format on the changes made in the last few
revisions you could use:
${i}\$ $bash_source HEAD~3${n}
${b}FILES${n}
List of files to completely reformat.
${b}-f, --whole-file${n}
Reformat the specified files completely (including parts you didn't
change).
The fix is printed on stdout by default. Use -i if you want to modify
the files on disk.
${b}--staged, --cached${n}
Reformat only code which is staged for commit.
The fix is printed on stdout by default. Use -i if you want to modify
the files on disk.
${b}-i${n}
Reformat the code and apply the changes to the files on disk (instead
of just printing the fix on stdout).
${b}--apply-to-staged${n}
This is like specifying both --staged and -i, but the formatting
changes are also staged for commit (so you can just use "git commit"
to commit what you planned to, but formatted correctly).
${b}--style STYLE${n}
The style to use for reformatting code.
If no style is specified, then it's assumed there's a .clang-format
file in the current directory or one of its parents.
${b}--help, -h, -?${n}
Show this help.
EOF
}
# getopts doesn't support long options.
# getopt mangles stuff.
# So we parse manually...
declare positionals=()
declare has_positionals=false
declare whole_file=false
declare apply_to_staged=false
declare staged=false
declare in_place=false
declare style=file
declare ignored=()
while [ $# -gt 0 ]; do
declare arg="$1"
shift # Past option.
case "$arg" in
-h | -\? | --help )
show_help
exit 0
;;
-f | --whole-file )
whole_file=true
;;
--apply-to-staged )
apply_to_staged=true
;;
--cached | --staged )
staged=true
;;
-i )
in_place=true
;;
--style=* )
style="${arg//--style=/}"
;;
--style )
[ $# -gt 0 ] || \
error_exit "No argument for --style option."
style="$1"
shift
;;
--internal-opt-ignore-regex=* )
ignored+=("${arg//--internal-opt-ignore-regex=/}")
;;
--internal-opt-ignore-regex )
ignored+=("${arg//--internal-opt-ignore-regex=/}")
[ $# -gt 0 ] || \
error_exit "No argument for --internal-opt-ignore-regex option."
ignored+=("$1")
shift
;;
-- )
# Stop processing further arguments.
if [ $# -gt 0 ]; then
positionals+=("$@")
has_positionals=true
fi
break
;;
-* )
error_exit "Unknown argument: $arg"
;;
*)
positionals+=("$arg")
;;
esac
done
# Restore positional arguments, access them from "$@".
if [ ${#positionals[@]} -gt 0 ]; then
set -- "${positionals[@]}"
has_positionals=true
fi
[ -n "$style" ] || \
error_exit "If you use --style you need to specify a valid style."
#######################################
# Detection of clang-format & friends #
#######################################
# clang-format.
declare format="${CLANG_FORMAT:-}"
if [ -z "$format" ]; then
format=$(type -p clang-format)
fi
if [ -z "$format" ]; then
error_exit \
$'You need to install clang-format.\n' \
$'\n' \
$'On Ubuntu/Debian this is available in the clang-format package or, in\n' \
$'older distro versions, clang-format-VERSION.\n' \
$'On Fedora it\'s available in the clang package.\n' \
$'You can also specify your own path for clang-format by setting the\n' \
$'$CLANG_FORMAT environment variable.'
fi
# clang-format-diff.
if [ "$whole_file" = false ]; then
invalid="/dev/null/invalid/path"
if [ "${OSTYPE:-}" = "linux-gnu" ]; then
readonly sort_version=-V
else
# On macOS, sort doesn't have -V.
readonly sort_version=-n
fi
declare paths_to_try=()
# .deb packages directly from upstream.
# We try these first as they are probably newer than the system ones.
while read -r f; do
paths_to_try+=("$f")
done < <(compgen -G "/usr/share/clang/clang-format-*/clang-format-diff.py" | sort "$sort_version" -r)
# LLVM official releases (just untarred in /usr/local).
while read -r f; do
paths_to_try+=("$f")
done < <(compgen -G "/usr/local/clang+llvm*/share/clang/clang-format-diff.py" | sort "$sort_version" -r)
# Maybe it's in the $PATH already? This is true for Ubuntu and Debian.
paths_to_try+=( \
"$(type -p clang-format-diff 2> /dev/null || echo "$invalid")" \
"$(type -p clang-format-diff.py 2> /dev/null || echo "$invalid")" \
)
# Fedora.
paths_to_try+=( \
/usr/share/clang/clang-format-diff.py \
)
# Gentoo.
while read -r f; do
paths_to_try+=("$f")
done < <(compgen -G "/usr/lib/llvm/*/share/clang/clang-format-diff.py" | sort -n -r)
# Homebrew.
while read -r f; do
paths_to_try+=("$f")
done < <(compgen -G "/usr/local/Cellar/clang-format/*/share/clang/clang-format-diff.py" | sort -n -r)
declare format_diff=
# Did the user specify a path?
if [ -n "${CLANG_FORMAT_DIFF:-}" ]; then
format_diff="$CLANG_FORMAT_DIFF"
else
for path in "${paths_to_try[@]}"; do
if [ -e "$path" ]; then
# Found!
format_diff="$path"
if [ ! -x "$format_diff" ]; then
format_diff="python $format_diff"
fi
break
fi
done
fi
if [ -z "$format_diff" ]; then
error_exit \
$'Cannot find clang-format-diff which should be shipped as part of the same\n' \
$'package where clang-format is.\n' \
$'\n' \
$'Please find out where clang-format-diff is in your distro and report an issue\n' \
$'at https://github.com/barisione/clang-format-hooks/issues with details about\n' \
$'your operating system and setup.\n' \
$'\n' \
$'You can also specify your own path for clang-format-diff by setting the\n' \
$'$CLANG_FORMAT_DIFF environment variable, for instance:\n' \
$'\n' \
$' CLANG_FORMAT_DIFF="python /.../clang-format-diff.py" \\\n' \
$' ' "$bash_source"
fi
readonly format_diff
fi
############################
# Actually run the command #
############################
if [ "$whole_file" = true ]; then
[ "$has_positionals" = true ] || \
error_exit "No files to reformat specified."
[ "$staged" = false ] || \
error_exit "--staged/--cached only make sense when applying to a diff."
read -r -a format_args <<< "$format"
format_args+=("-style=file")
[ "$in_place" = true ] && format_args+=("-i")
"${format_args[@]}" "$@"
else # Diff-only.
if [ "$apply_to_staged" = true ]; then
[ "$staged" = false ] || \
error_exit "You don't need --staged/--cached with --apply-to-staged."
[ "$in_place" = false ] || \
error_exit "You don't need -i with --apply-to-staged."
staged=true
readonly patch_dest=$(mktemp)
trap '{ rm -f "$patch_dest"; }' EXIT
else
readonly patch_dest=/dev/stdout
fi
declare git_args=(git diff -U0 --no-color)
[ "$staged" = true ] && git_args+=("--staged")
# $format_diff may contain a command ("python") and the script to excute, so we
# need to split it.
read -r -a format_diff_args <<< "$format_diff"
[ "$in_place" = true ] && format_diff_args+=("-i")
# Build the regex for paths to consider or ignore.
# We use negative lookahead assertions which preceed the list of allowed patterns
# (that is, the extensions we want).
exclusions_regex=
if [ "${#ignored[@]}" -gt 0 ]; then
for pattern in "${ignored[@]}"; do
exclusions_regex="$exclusions_regex(?!$pattern)"
done
fi
"${git_args[@]}" "$@" \
| "${format_diff_args[@]}" \
-p1 \
-style="$style" \
-iregex="$exclusions_regex"'.*\.(c|cpp|cxx|cc|h|hpp|m|mm|js|java)' \
> "$patch_dest" \
|| exit 1
if [ "$apply_to_staged" = true ]; then
if [ ! -s "$patch_dest" ]; then
echo "No formatting changes to apply."
exit 0
fi
patch -p0 < "$patch_dest" || \
error_exit "Cannot apply fix to local files."
git apply -p0 --cached < "$patch_dest" || \
error_exit "Cannot apply fix to git staged changes."
fi
fi

Some files were not shown because too many files have changed in this diff Show More