Compare commits

..

3 Commits
master ... ep9

184 changed files with 12266 additions and 11502 deletions

View File

@ -15,20 +15,4 @@ AlignConsecutiveBitFields: Consecutive
AlignEscapedNewlines: Left
AlwaysBreakTemplateDeclarations: Yes
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^"'
Priority: 1
SortPriority: 1
CaseSensitive: true
- Regex: '^<(llvm|llvm-c|clang|clang-c|mlir)/'
Priority: 3
SortPriority: 3
CaseSensitive: true
- Regex: '<[[:alnum:].]+>'
Priority: 5
- Regex: '.*'
Priority: 2
SortPriority: 0
SortIncludes: true
SortUsingDeclarations: true
...

View File

@ -1,237 +0,0 @@
---
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*'
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
FormatStyle: file
User: lxsameer
CheckOptions:
- key: performance-unnecessary-copy-initialization.ExcludedContainerTypes
value: ''
- key: readability-suspicious-call-argument.PrefixSimilarAbove
value: '30'
- key: modernize-replace-auto-ptr.IncludeStyle
value: llvm
- key: performance-move-const-arg.CheckTriviallyCopyableMove
value: 'true'
- key: readability-static-accessed-through-instance.NameSpecifierNestingThreshold
value: '3'
- key: readability-function-size.VariableThreshold
value: '4294967295'
- key: readability-simplify-subscript-expr.Types
value: '::std::basic_string;::std::basic_string_view;::std::vector;::std::array'
- key: cert-dcl16-c.NewSuffixes
value: 'L;LL;LU;LLU'
- key: cert-dcl51-cpp.AggressiveDependentMemberLookup
value: 'false'
- key: readability-identifier-naming.GetConfigPerFile
value: 'true'
- key: cert-err61-cpp.MaxSize
value: '0'
- key: cert-sig30-c.AsyncSafeFunctionSet
value: POSIX
- key: readability-inconsistent-declaration-parameter-name.Strict
value: 'false'
- key: readability-suspicious-call-argument.DiceDissimilarBelow
value: '60'
- key: cert-dcl37-c.AllowedIdentifiers
value: ''
- key: readability-function-size.NestingThreshold
value: '4294967295'
- key: llvm-namespace-comment.ShortNamespaceLines
value: '1'
- key: llvm-namespace-comment.SpacesBeforeComments
value: '1'
- key: readability-function-size.ParameterThreshold
value: '4294967295'
- key: readability-suspicious-call-argument.Equality
value: 'true'
- key: readability-function-cognitive-complexity.IgnoreMacros
value: 'false'
- key: cert-str34-c.DiagnoseSignedUnsignedCharComparisons
value: 'false'
- key: readability-identifier-naming.AggressiveDependentMemberLookup
value: 'false'
- key: readability-redundant-smartptr-get.IgnoreMacros
value: 'true'
- key: cert-err61-cpp.WarnOnLargeObjects
value: 'false'
- key: cert-err09-cpp.WarnOnLargeObjects
value: 'false'
- key: google-readability-namespace-comments.ShortNamespaceLines
value: '10'
- key: readability-suspicious-call-argument.JaroWinklerDissimilarBelow
value: '75'
- key: readability-suspicious-call-argument.SuffixSimilarAbove
value: '30'
- key: readability-suspicious-call-argument.Suffix
value: 'true'
- key: cert-oop57-cpp.MemSetNames
value: ''
- key: performance-type-promotion-in-math-fn.IncludeStyle
value: llvm
- key: readability-function-cognitive-complexity.DescribeBasicIncrements
value: 'true'
- key: readability-suspicious-call-argument.MinimumIdentifierNameLength
value: '3'
- key: modernize-loop-convert.NamingStyle
value: CamelCase
- key: readability-inconsistent-declaration-parameter-name.IgnoreMacros
value: 'true'
- key: performance-no-automatic-move.AllowedTypes
value: ''
- key: readability-suspicious-call-argument.SubstringDissimilarBelow
value: '40'
- key: performance-for-range-copy.WarnOnAllAutoCopies
value: 'false'
- key: readability-identifier-naming.IgnoreFailedSplit
value: 'false'
- key: modernize-pass-by-value.IncludeStyle
value: llvm
- key: readability-qualified-auto.AddConstToQualified
value: 'true'
- key: readability-simplify-boolean-expr.ChainedConditionalReturn
value: 'false'
- key: readability-else-after-return.WarnOnConditionVariables
value: 'true'
- key: readability-uppercase-literal-suffix.IgnoreMacros
value: 'true'
- key: modernize-use-nullptr.NullMacros
value: 'NULL'
- key: cert-dcl59-cpp.HeaderFileExtensions
value: ';h;hh;hpp;hxx'
- key: readability-suspicious-call-argument.SuffixDissimilarBelow
value: '25'
- key: performance-unnecessary-copy-initialization.AllowedTypes
value: ''
- key: llvm-header-guard.HeaderFileExtensions
value: ';h;hh;hpp;hxx'
- key: readability-suspicious-call-argument.LevenshteinSimilarAbove
value: '66'
- key: readability-suspicious-call-argument.Levenshtein
value: 'true'
- key: readability-suspicious-call-argument.JaroWinkler
value: 'true'
- key: readability-suspicious-call-argument.Prefix
value: 'true'
- key: readability-simplify-boolean-expr.ChainedConditionalAssignment
value: 'false'
- key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField
value: 'false'
- key: cert-err09-cpp.CheckThrowTemporaries
value: 'true'
- key: cert-dcl51-cpp.Invert
value: 'false'
- key: readability-function-size.LineThreshold
value: '4294967295'
- key: modernize-loop-convert.MaxCopySize
value: '16'
- key: readability-suspicious-call-argument.PrefixDissimilarBelow
value: '25'
- key: performance-inefficient-vector-operation.EnableProto
value: 'false'
- key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors
value: 'true'
- key: performance-for-range-copy.AllowedTypes
value: ''
- key: readability-redundant-string-init.StringNames
value: '::std::basic_string_view;::std::basic_string'
- key: readability-magic-numbers.IgnoreBitFieldsWidths
value: 'true'
- key: readability-braces-around-statements.ShortStatementLines
value: '0'
- key: readability-suspicious-call-argument.LevenshteinDissimilarBelow
value: '50'
- key: readability-magic-numbers.IgnoredFloatingPointValues
value: '1.0;100.0;'
- key: readability-redundant-declaration.IgnoreMacros
value: 'true'
- key: performance-inefficient-string-concatenation.StrictMode
value: 'false'
- key: concurrency-mt-unsafe.FunctionSet
value: any
- key: readability-implicit-bool-conversion.AllowPointerConditions
value: 'false'
- key: google-readability-braces-around-statements.ShortStatementLines
value: '1'
- key: readability-else-after-return.WarnOnUnfixable
value: 'true'
- key: cert-dcl51-cpp.AllowedIdentifiers
value: ''
- key: cert-oop57-cpp.MemCpyNames
value: ''
- key: readability-suspicious-call-argument.SubstringSimilarAbove
value: '50'
- key: readability-suspicious-call-argument.Substring
value: 'true'
- key: readability-magic-numbers.IgnoreAllFloatingPointValues
value: 'false'
- key: readability-suspicious-call-argument.Abbreviations
value: 'arr=array;cnt=count;idx=index;src=source;stmt=statement;cpy=copy;dest=destination;dist=distancedst=distance;ptr=pointer;wdth=width;str=string;ln=line;srv=server;attr=attribute;ref=reference;buf=buffer;col=column;nr=number;vec=vector;len=length;elem=element;val=value;i=index;var=variable;hght=height;cl=client;num=number;pos=position;lst=list;addr=address'
- key: readability-uppercase-literal-suffix.NewSuffixes
value: ''
- key: modernize-loop-convert.MinConfidence
value: reasonable
- key: performance-unnecessary-value-param.AllowedTypes
value: ''
- key: readability-uniqueptr-delete-release.PreferResetCall
value: 'false'
- key: cert-oop57-cpp.MemCmpNames
value: ''
- key: google-readability-namespace-comments.SpacesBeforeComments
value: '2'
- key: readability-function-cognitive-complexity.Threshold
value: '25'
- key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
value: 'true'
- key: cert-err61-cpp.CheckThrowTemporaries
value: 'true'
- key: performance-faster-string-find.StringLikeClasses
value: '::std::basic_string;::std::basic_string_view'
- key: readability-function-size.BranchThreshold
value: '4294967295'
- key: readability-implicit-bool-conversion.AllowIntegerConditions
value: 'false'
- key: readability-function-size.StatementThreshold
value: '800'
- key: readability-identifier-naming.IgnoreMainLikeFunctions
value: 'false'
- key: llvm-qualified-auto.AddConstToQualified
value: 'false'
- key: cert-str34-c.CharTypdefsToIgnore
value: ''
- key: google-readability-function-size.StatementThreshold
value: '800'
- key: llvm-else-after-return.WarnOnConditionVariables
value: 'false'
- key: cert-msc51-cpp.DisallowedSeedTypes
value: 'time_t,std::time_t'
- key: readability-suspicious-call-argument.DiceSimilarAbove
value: '70'
- key: readability-suspicious-call-argument.Dice
value: 'true'
- key: readability-suspicious-call-argument.Abbreviation
value: 'true'
- key: cert-dcl37-c.Invert
value: 'false'
- key: cert-dcl37-c.AggressiveDependentMemberLookup
value: 'false'
- key: performance-inefficient-vector-operation.VectorLikeClasses
value: '::std::vector'
- key: readability-magic-numbers.IgnoredIntegerValues
value: '1;2;3;4;'
- key: readability-magic-numbers.IgnorePowersOf2IntegerValues
value: 'false'
- key: readability-redundant-member-init.IgnoreBaseInCopyConstructors
value: 'false'
- key: readability-suspicious-call-argument.JaroWinklerSimilarAbove
value: '85'
- key: cert-dcl16-c.IgnoreMacros
value: 'true'
- key: performance-unnecessary-value-param.IncludeStyle
value: llvm
- key: llvm-else-after-return.WarnOnUnfixable
value: 'false'
- key: cert-msc32-c.DisallowedSeedTypes
value: 'time_t,std::time_t'
...

View File

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

11
.gitignore vendored
View File

@ -23,14 +23,3 @@ 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

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,20 @@
# 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/>.
cmake_minimum_required(VERSION 3.19)
cmake_minimum_required(VERSION 3.16)
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)
option(CPP_20_SUPPORT "C++20 Support" OFF)
# =============================================================================
# Policies
# =============================================================================
cmake_policy(SET CMP0116 OLD)
# =============================================================================
# User Options
# =============================================================================
option(CPP_20_SUPPORT "C++20 Support" ON)
option(SERENE_BUILD_TESTING "Enable tests" ON)
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)
# Only do these if this is the main project, and not if it is included through
# add_subdirectory
# 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,145 +22,105 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
set(CMAKE_CXX_STANDARD_REQUIRED True)
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})
set(INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include)
set(SRC_DIR ${CMAKE_SOURCE_DIR}/src)
set(BIN_DIR ${CMAKE_SOURCE_DIR}/bin)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror")
#set(CMAKE_CXX_LINK_EXECUTABLE "ld.lld")
#set(CMAKE_C_LINK_EXECUTABLE "ld.lld")
#set(LLVM_USE_LINKER "ld.lld")
#set(LLVM_ENABLE_LLD ON)
set(CMAKE_CXX_CLANG_TIDY clang-tidy)
# Let's ensure -std=c++xx instead of -std=g++xx
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_FLAGS_DEBUG
"${CMAKE_CXX_FLAGS_DEBUG} -g -fno-omit-frame-pointer $ENV{ASAN_FLAG} -fno-builtin-strlen -ggdb -fno-inline -fdebug-prefix-map=$PWD=.")
set(CMAKE_LINKER_FLAGS_DEBUG
"${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer $ENV{ASAN_FLAG}")
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
set(CMAKE_CXX_FLAGS_RELEASE
"${CMAKE_CXX_FLAGS_RELEASE} -O3")
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/scripts/cmake")
set(MemoryCheckCommand "valgrind")
add_compile_options(-fno-rtti)
configure_file(${INCLUDE_DIR}/config.h.in config.h)
# Let's nicely support folders in IDEs
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# Setup the basic compiler flags
add_compile_options(
-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)
## Options ------------------------------------------
option(ENABLE_LOG "Enable logging" OFF)
option(ENABLE_EXPR_LOG "Enable AExpr logging" OFF)
option(ENABLE_READER_LOG "Enable reader logging" OFF)
option(BUILD_TESTING "Enable tests" OFF)
# 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")
include(cotire)
include(FetchContent)
set(CCACHE_PROGRAM "${SERENE_CCACHE_PARAMS} ${CCACHE_PROGRAM}")
if(SERENE_CCACHE_MAXSIZE)
set(CCACHE_PROGRAM
"CCACHE_MAXSIZE=${SERENE_CCACHE_MAXSIZE} ${CCACHE_PROGRAM}")
endif()
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")
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
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 "Found LLVM ${LLVM_PAsCKAGE_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}")
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})
include_directories(${LLVM_INCLUDE_DIRS})
include_directories(${MLIR_INCLUDE_DIRS})
include_directories(${PROJECT_SOURCE_DIR}/include)
include_directories(${PROJECT_BINARY_DIR}/include)
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
include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
# 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)
llvm_map_components_to_libnames(llvm_libs support core irreader)
# add_subdirectory(devtools)
# The compiled library code is here
add_subdirectory(src/serene)
if(SERENE_ENABLE_DOCS)
add_subdirectory(docs)
# The executable code is here
add_subdirectory(bin)
add_subdirectory(include)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/include/)
# Testing only available if this is the main app
# Emergency override SERENE_CMAKE_BUILD_TESTING provided as well
if(BUILD_TESTING)
message("Build the test binary")
add_subdirectory(src/tests)
endif()
if (CMAKE_BUILD_TYPE STREQUAL "Release")
# 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()

352
LICENSE Normal file → Executable file
View File

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

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/>.

75
README.org Normal file
View File

@ -0,0 +1,75 @@
* 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=.
* 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]]
* 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

39
bin/CMakeLists.txt Normal file
View File

@ -0,0 +1,39 @@
add_executable(serenec serene.cpp)
# Make sure to generate files related to the dialects first
#add_dependencies(serenec SereneDialectGen)
if (CPP_20_SUPPORT)
target_compile_features(serenec PRIVATE cxx_std_20)
else()
target_compile_features(serenec PRIVATE cxx_std_17)
endif()
target_link_libraries(serenec PRIVATE
serene
${llvm_libs}
MLIRAnalysis
MLIRIR
MLIRParser
MLIRSideEffectInterfaces
MLIRTransforms
LLVMX86AsmParser
LLVMOption
#clangTooling
clangDriver
clangBasic
clangdSupport
clangFrontend
clangEdit
clangLex
)
target_include_directories(serene SYSTEM PRIVATE $ENV{INCLUDE})
target_include_directories(serene PRIVATE ${INCLUDE_DIR})
install(TARGETS serenec DESTINATION bin)
install(FILES "${PROJECT_BINARY_DIR}/config.h" DESTINATION include)

360
bin/serene.cpp Normal file
View File

@ -0,0 +1,360 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "serene/serene.h"
#include "serene/context.h"
#include "serene/jit.h"
#include "serene/namespace.h"
#include "serene/reader/reader.h"
#include "serene/reader/semantics.h"
#include "serene/slir/generatable.h"
#include "serene/slir/slir.h"
#include <clang/Driver/Compilation.h>
#include <clang/Driver/Driver.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
#include <clang/Tooling/Tooling.h>
#include <llvm/ADT/ArrayRef.h>
#include <llvm/ADT/SmallString.h>
#include <llvm/ADT/StringRef.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/Support/CommandLine.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/raw_ostream.h>
#include <llvm/Target/TargetMachine.h>
#include <llvm/Target/TargetOptions.h>
#include <memory>
using namespace std;
using namespace serene;
namespace cl = llvm::cl;
namespace {
enum Action {
None,
DumpAST,
DumpSLIR,
DumpMLIR,
DumpSemantic,
DumpLIR,
DumpIR,
CompileToObject,
Compile,
// TODO: Remove this option and replace it by a subcommand
RunJIT,
};
}
static cl::opt<std::string> inputFile(cl::Positional,
cl::desc("The Serene file to compile"),
cl::init("-"),
cl::value_desc("filename"));
static cl::opt<std::string> outputFile(
"o", cl::desc("The relative path to the output file from the build dir"),
cl::init("-"), cl::value_desc("filename"));
static cl::opt<std::string>
outputDir("build-dir", cl::desc("The absolute path to the build directory"),
cl::init("-"), cl::value_desc("filename"));
static cl::opt<enum Action> emitAction(
"emit", cl::desc("Select what to dump."), cl::init(Compile),
cl::values(clEnumValN(DumpSemantic, "semantic",
"Output the AST after one level of analysis only")),
cl::values(clEnumValN(DumpIR, "ir", "Output the lowered IR only")),
cl::values(clEnumValN(DumpSLIR, "slir", "Output the SLIR only")),
cl::values(clEnumValN(DumpMLIR, "mlir",
"Output the MLIR only (Lowered SLIR)")),
cl::values(clEnumValN(DumpLIR, "lir",
"Output the LIR only (Lowerd to LLVM dialect)")),
cl::values(clEnumValN(DumpAST, "ast", "Output the AST only")),
cl::values(clEnumValN(CompileToObject, "object",
"Compile to object file.")),
cl::values(clEnumValN(Compile, "target",
"Compile to target code. (Default)")),
cl::values(clEnumValN(RunJIT, "jit",
"Run the give input file with the JIT."))
);
exprs::Ast readInputFile() {
auto r = make_unique<reader::FileReader>(inputFile);
auto maybeAst = r->read();
if (!maybeAst) {
throw std::move(maybeAst.getError());
}
return maybeAst.getValue();
};
exprs::Ast readAndAnalyze(SereneContext &ctx) {
auto ast = readInputFile();
auto afterAst = reader::analyze(ctx, ast);
if (!afterAst) {
throw std::move(afterAst.getError());
}
return afterAst.getValue();
};
int dumpAsObject(Namespace &ns) {
// TODO: Move the compilation process to the Namespace class
auto maybeModule = ns.compileToLLVM();
// TODO: Fix this call to raise the wrapped error instead
auto module = std::move(
maybeModule.getValueOrFail("Faild to generato LLVM IR for namespace"));
auto &ctx = ns.getContext();
// TODO: We need to set the triple data layout and everything to that sort in
// one place. We want them for the JIT as well and also we're kinda
// duplicating what we're doing in `Namespace#compileToLLVM`.
module->setTargetTriple(ctx.targetTriple);
std::string Error;
auto target = llvm::TargetRegistry::lookupTarget(ctx.targetTriple, Error);
// Print an error and exit if we couldn't find the requested target.
// This generally occurs if we've forgotten to initialise the
// TargetRegistry or we have a bogus target triple.
if (!target) {
llvm::errs() << Error;
return 1;
}
auto cpu = "generic";
auto features = "";
llvm::TargetOptions opt;
auto rm = llvm::Optional<llvm::Reloc::Model>();
auto targetMachinePtr =
target->createTargetMachine(ctx.targetTriple, cpu, features, opt, rm);
auto targetMachine = std::unique_ptr<llvm::TargetMachine>(targetMachinePtr);
module->setDataLayout(targetMachine->createDataLayout());
auto filename =
strcmp(outputFile.c_str(), "-") == 0 ? "output" : outputFile.c_str();
std::error_code ec;
llvm::SmallString<256> destFile(outputDir);
llvm::sys::path::append(destFile, filename);
auto destObjFilePath = llvm::formatv("{0}.o", destFile).str();
llvm::raw_fd_ostream dest(destObjFilePath, ec, llvm::sys::fs::OF_None);
if (ec) {
llvm::errs() << "Could not open file: " << ec.message();
return 1;
}
llvm::legacy::PassManager pass;
auto fileType = llvm::CGFT_ObjectFile;
if (targetMachine->addPassesToEmitFile(pass, dest, nullptr, fileType)) {
llvm::errs() << "TheTargetMachine can't emit a file of this type";
return 1;
}
pass.run(*module);
dest.flush();
if (emitAction == Action::Compile) {
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> opts =
new clang::DiagnosticOptions;
clang::DiagnosticsEngine diags(
new clang::DiagnosticIDs, opts,
new clang::TextDiagnosticPrinter(llvm::errs(), opts.get()));
clang::driver::Driver d("clang", ctx.targetTriple, diags,
"Serene compiler");
std::vector<const char *> args = {"serenec"};
args.push_back(destObjFilePath.c_str());
args.push_back("-o");
args.push_back(destFile.c_str());
d.setCheckInputsExist(false);
std::unique_ptr<clang::driver::Compilation> compilation;
compilation.reset(d.BuildCompilation(args));
if (!compilation) {
return 1;
}
llvm::SmallVector<std::pair<int, const clang::driver::Command *>>
failCommand;
// compilation->ExecuteJobs(compilation->getJobs(), failCommand);
d.ExecuteCompilation(*compilation, failCommand);
if (failCommand.empty()) {
llvm::outs() << "Done!\n";
} else {
llvm::errs() << "Linking failed!\n";
}
}
return 0;
};
int main(int argc, char *argv[]) {
// mlir::registerAsmPrinterCLOptions();
mlir::registerMLIRContextCLOptions();
mlir::registerPassManagerCLOptions();
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmParsers();
llvm::InitializeAllAsmPrinters();
cl::ParseCommandLineOptions(argc, argv, "Serene compiler \n");
auto ctx = makeSereneContext();
auto ns = makeNamespace(*ctx, "user", llvm::None);
// TODO: We might want to find a better place for this
applyPassManagerCLOptions(ctx->pm);
// TODO: handle the outputDir by not forcing it. it should be
// default to the current working dir
if (outputDir == "-") {
llvm::errs() << "Error: The build directory is not set. Did you forget to "
"use '-build-dir'?\n";
return 1;
}
switch (emitAction) {
case Action::RunJIT: {
// TODO: Replace it by a proper jit configuration
ctx->setOperationPhase(CompilationPhase::NoOptimization);
break;
};
// Just print out the raw AST
case Action::DumpAST: {
auto ast = readInputFile();
llvm::outs() << exprs::astToString(&ast) << "\n";
return 0;
};
case Action::DumpSemantic: {
auto ast = readAndAnalyze(*ctx);
llvm::outs() << exprs::astToString(&ast) << "\n";
return 0;
};
case Action::DumpSLIR: {
ctx->setOperationPhase(CompilationPhase::SLIR);
break;
}
case Action::DumpMLIR: {
ctx->setOperationPhase(CompilationPhase::MLIR);
break;
}
case Action::DumpLIR: {
ctx->setOperationPhase(CompilationPhase::LIR);
break;
}
case Action::DumpIR: {
ctx->setOperationPhase(CompilationPhase::IR);
break;
}
case Action::CompileToObject: {
ctx->setOperationPhase(CompilationPhase::NoOptimization);
break;
}
case Action::Compile: {
ctx->setOperationPhase(CompilationPhase::NoOptimization);
break;
}
default: {
llvm::errs() << "No action specified. TODO: Print out help here\n";
return 1;
}
}
auto afterAst = readAndAnalyze(*ctx);
auto isSet = ns->setTree(afterAst);
if (isSet.succeeded()) {
ctx->insertNS(ns);
switch (emitAction) {
case Action::DumpSLIR:
case Action::DumpMLIR:
case Action::DumpLIR: {
ns->dump();
break;
};
case Action::DumpIR: {
auto maybeModule = ns->compileToLLVM();
if (!maybeModule) {
llvm::errs() << "Failed to generate the IR.\n";
return 1;
}
maybeModule.getValue()->dump();
break;
};
case Action::RunJIT: {
auto maybeJIT = JIT::make(*ns.get());
auto jit = std::move(maybeJIT.getValueOrFail("Couldn't creat the JIT!"));
if (jit->invoke("main")) {
llvm::errs() << "Faild to invoke the 'main' function.\n";
return 1;
}
llvm::outs() << "Done!";
break;
};
case Action::Compile:
case Action::CompileToObject: {
return dumpAsObject(*ns);
};
default: {
llvm::errs() << "Action is not supported yet!\n";
};
}
} else {
llvm::errs() << "Can't set the tree of the namespace!\n";
}
return 0;
}

209
builder Executable file
View File

@ -0,0 +1,209 @@
#! /bin/bash
command=$1
# Utilize `ccache` if available
if type "ccache" > /dev/null
then
echo "CCache detected."
CMAKE_CCACHE="-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache"
else
echo "CCache not detected."
CMAKE_CCACHE=""
fi
export CMAKE_CCACHE
export CC=$(which clang)
export CXX=$(which clang++)
export CCACHE_SLOPPINESS="pch_defines,time_macros"
# Meke sure to use `lld` linker it faster and has a better UX
export LDFLAGS="-fuse-ld=lld"
export ASAN_FLAG="-fsanitize=address"
export ASAN_OPTIONS=check_initialization_order=1
LSAN_OPTIONS=suppressions=$(pwd)/.ignore_sanitize
export LSAN_OPTIONS
# The `builder` script is supposed to be run from the
# root of the source tree
ROOT_DIR=$(pwd)
BUILD_DIR=$ROOT_DIR/build
scanbuild=scan-build
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 compile() {
pushed_build
ninja -j "$(nproc)"
popd_build
}
function build() {
pushed_build
echo "Running: "
echo "cmake -G Ninja $CMAKE_CCACHE -DCMAKE_BUILD_TYPE=Debug \"$@\" \"$ROOT_DIR\""
cmake -G Ninja $CMAKE_CCACHE -DCMAKE_BUILD_TYPE=Debug "$@" "$ROOT_DIR"
ninja -j "$(nproc)"
popd_build
}
function build-20() {
pushed_build
cmake -G Ninja $CMAKE_CCACHE -DCMAKE_BUILD_TYPE=Debug -DCPP_20_SUPPORT=ON "$@" "$ROOT_DIR"
ninja -j "$(nproc)"
popd_build
}
function build-release() {
pushed_build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release "$ROOT_DIR"
ninja -j "$(nproc)"
popd_build
}
function build-docs() {
pushed_build
cmake -G Ninja $CMAKE_CCACHE -DCMAKE_BUILD_TYPE=Docs "$ROOT_DIR"
ninja -j "$(nproc)"
popd_build
}
function clean() {
rm -rf "$BUILD_DIR"
}
function run() {
pushed_build
"$BUILD_DIR"/bin/serenec "$@"
popd_build
}
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() {
"$BUILD_DIR"/src/tests/tests
}
function tests() {
pushed_build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON "$ROOT_DIR"
ninja -j "$(nproc)"
popd_build
}
case "$command" in
"setup")
pushd ./scripts || return
./git-pre-commit-format install
popd || return
echo "=== Manual action required ==="
echo "Set this environment variable. (clang-format-diff.py is located inside llvm's source directory)."
echo 'export CLANG_FORMAT_DIFF="python3 /path/to/llvm/saurce/llvm-project/clang/tools/clang-format/clang-format-diff.py"'
;;
"build")
clean
mkdir -p "$BUILD_DIR"
build "${@: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}"
;;
"run-tests")
run-tests "${@:2}"
;;
"scan-build")
clean
mkdir -p "$BUILD_DIR"
pushed_build
exec $scanbuild cmake "$ROOT_DIR"
exec $scanbuild scan-build make -j 4
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,29 +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/>.
*/
#ifndef SERENE_CORE_CORE_H
#define SERENE_CORE_CORE_H
#include "serene/export.h"
namespace serene {
extern "C" int SERENE_EXPORT read() asm("serene.core/read");
extern "C" int SERENE_EXPORT compile() asm("serene.core/compile");
} // namespace serene
#endif

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,31 +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/core/core.h"
#include "serene/types/types.h"
#include <cstdio>
namespace serene {
extern "C" int SERENE_EXPORT compile() {
printf("compile11\n");
return 2;
};
} // namespace serene

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>

View File

@ -1,26 +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/core/core.h"
#include "serene/types/types.h"
namespace serene {
int read() { return 0; };
} // namespace serene

161
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,32 +62,18 @@ 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]]
** Compiler
- [[https://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64][Stack frame layout on x86-64]]
*** Branch instructions
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,87 +93,19 @@ 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
So we can use them directly via command line, like -O1 for example
** 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:
CLOSED: [2021-09-25 Sat 19:22]
:LOGBOOK:
- State "DONE" from "TODO" [2021-09-25 Sat 19:22]
:END:
** Bootstrap*
*** TODO Add the support for =ns-paths= :serenecli:context:
We need to add the support for an array of paths to lookup namespaces. The =ns-paths= should
be an array that each entry represents a path which serene has to look into in order to find
a namespace. For instance, when serene wants to load the =foo.bar= namespace, it should walk
@ -206,39 +115,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,35 +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/slir/dialect.h"
#include <mlir/Dialect/Func/IR/FuncOps.h>
#include <mlir/IR/Dialect.h>
#include <mlir/Tools/mlir-lsp-server/MlirLspServerMain.h>
int main(int argc, char **argv) {
mlir::DialectRegistry registry;
serene::slir::registerTo(registry);
registry.insert<mlir::func::FuncDialect>();
// TODO: Register passes here
return static_cast<int>(
mlir::failed(mlir::MlirLspServerMain(argc, argv, registry)));
}

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,2 @@
(def main (fn () 4))
(def main (fn () 3))
(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
@ -377,8 +377,7 @@ Output:
- https://mlir.llvm.org/docs/LangRef
- https://en.wikipedia.org/wiki/Basic_block
* DONE Episode 9 - IR (SLIR) generation
CLOSED: [2021-10-01 Fri 18:56]
* Episode 9 - IR (SLIR) generation
** Updates:
- Source manager
- Diagnostic Engine
@ -403,680 +402,3 @@ There will be an episode dedicated to eache of these
- [X] Setup the tablegen
- [X] Define the operations
- [X] Walk the AST and generate the operations
* DONE Episode 10 - Pass Infrastructure
CLOSED: [2021-10-15 Fri 14:17]
** The next Step
** Updates:
*** CMake changes
** What is a Pass
*** Passes are the unit of abstraction for optimization and transformation in LLVM/MLIR
*** Compilation is all about transforming the input data and produce an output
Source code -> IR X -> IR Y -> IR Z -> ... -> Target Code
*** Almost like a function composition
*** The big picture
*** Pass Managers (Pipelines) are made out of a collection of passes and can be nested
*** The most of the interesting parts of the compiler reside in Passes.
*** We will probably spend most of our time working with passes
** Pass Infrastructure
*** ODS or C++
*** Operation is the main abstract unit of transformation
*** OperationPass is the base class for all the passes.
*** We need to override =runOnOperation=
*** There's some rules you need to follow when defining your Pass
**** Must not maintain any global mutable state
**** Must not modify the state of another operation not nested within the current operation being operated on
**** ...
*** Passes are either OpSpecific or OpAgnostic
**** OpSpecific
#+BEGIN_SRC C++
struct MyFunctionPass : public PassWrapper<MyFunctionPass,
OperationPass<FuncOp>> {
void runOnOperation() override {
// Get the current FuncOp operation being operated on.
FuncOp f = getOperation();
// Walk the operations within the function.
f.walk([](Operation *inst) {
// ....
});
}
};
/// Register this pass so that it can be built via from a textual pass pipeline.
/// (Pass registration is discussed more below)
void registerMyPass() {
PassRegistration<MyFunctionPass>();
}
#+END_SRC
**** OpAgnostic
#+BEGIN_SRC C++
struct MyOperationPass : public PassWrapper<MyOperationPass, OperationPass<>> {
void runOnOperation() override {
// Get the current operation being operated on.
Operation *op = getOperation();
// ...
}
};
#+END_SRC
*** How transformation works?
*** Analyses and Passes
*** Pass management and nested pass managers
#+BEGIN_SRC C++
// Create a top-level `PassManager` class. If an operation type is not
// explicitly specific, the default is the builtin `module` operation.
PassManager pm(ctx);
// Note: We could also create the above `PassManager` this way.
PassManager pm(ctx, /*operationName=*/"builtin.module");
// Add a pass on the top-level module operation.
pm.addPass(std::make_unique<MyModulePass>());
// Nest a pass manager that operates on `spirv.module` operations nested
// directly under the top-level module.
OpPassManager &nestedModulePM = pm.nest<spirv::ModuleOp>();
nestedModulePM.addPass(std::make_unique<MySPIRVModulePass>());
// Nest a pass manager that operates on functions within the nested SPIRV
// module.
OpPassManager &nestedFunctionPM = nestedModulePM.nest<FuncOp>();
nestedFunctionPM.addPass(std::make_unique<MyFunctionPass>());
// Run the pass manager on the top-level module.
ModuleOp m = ...;
if (failed(pm.run(m))) {
// Handle the failure
}
#+END_SRC
* DONE Episode 11 - Lowering SLIR
CLOSED: [2021-11-01 Mon 15:14]
** Overview
- What is a Pass?
- Pass Manager
** Dialect lowering
*** Why?
*** Transforming a dialect to another dialect or LLVM IR
*** The goal is to lower SLIR to LLVM IR directly or indirectly.
** Dialect Conversions
This framework allows for transforming a set of illegal operations to a set of legal ones.
*** Target Conversion
*** Rewrite Patterns
*** Type Converter
** Full vs Partial Conversion
* DONE Episode 12 - Target code generation
CLOSED: [2021-11-04 Thu 00:57]
** Updates:
*** JIT work
*** Emacs dev mode
** So far....
** Next Step
*** Compile to object files
*** Link object files to create an executable
** End of wiring for static compilers
** What is an object file?
*** Symbols
- A pair of a name and a value
- Value of a *defined symbol* is an offset in the =Content=
- *undefined symbols*
*** Relocations
Are computation to perform on the =Content=. For example, "set
this location in the contents to the value of this symbol plus this addend".
Linker will apply all the *relocations* in an object file on link time and if
it can not resolve an undefined symbol most of the time it will raise an
error (depending on the relocation and the symbol).
*** Contents
- Are what memory should look like during the execution
- Have a size
- Have a type
- Have an array of bytes
- Has sections like:
+ .text: The target code generated by the compiler
+ .data: The values of initialized variables
+ .rdata: Static unnamed data like literal strings, protocol tables and ....
+ .bss: Uninitialized variables (the content can be omitted or striped and assume
to contain only zeros)
** Linking process
During the linking process, linker assigns an address to each *defined* symbol
and tries to =resolve= *undefined* symbols
*** Linker will
- reads the object files
- reads the contents
+ as raw data
+ figures out the length
+ reads the symbols and create a symbol table
+ link undefined symbols to their definitions (possibly from other obj fils or libs)
+ decide where all the content should go in the memory
+ sort them based on the *type*
+ concat them together
+ apply relocations
+ write the result to a file as an executable
** AOT vs JIT
** 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]
** FAQ:
- What tools are you using?
** Updates:
- Still JIT
- We're going to start the JIT discussion from next EP
** Forgot to show case the code generation
I didn't show it in action
** What is a source manager
- It owns and manages are the source buffers
- All of our interactions with source files will happen though Source manager
- Including reading files
- Loading namespaces
- Including namespaces
- ...
- 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/")

11
include/config.h.in Normal file
View File

@ -0,0 +1,11 @@
#ifndef CONFIG_H
#define CONFIG_H
// the configured options and settings for Tutorial
#define SERENE_VERSION_MAJOR @Serene_VERSION_MAJOR@
#define SERENE_VERSION_MINOR @Serene_VERSION_MINOR@
#cmakedefine ENABLE_READER_LOG
#cmakedefine ENABLE_EXPR_LOG
#cmakedefine ENABLE_LOG
#endif

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

@ -0,0 +1,126 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SERENE_CONTEXT_H
#define SERENE_CONTEXT_H
#include "serene/environment.h"
#include "serene/namespace.h"
#include "serene/passes.h"
#include "serene/slir/dialect.h"
#include <llvm/ADT/StringRef.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/Support/Host.h>
#include <memory>
#include <mlir/Dialect/StandardOps/IR/Ops.h>
#include <mlir/IR/MLIRContext.h>
#include <mlir/Pass/PassManager.h>
namespace serene {
namespace exprs {
class Expression;
using Node = std::shared_ptr<Expression>;
} // namespace exprs
enum class CompilationPhase {
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 SereneContext {
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::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(std::shared_ptr<Namespace> 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
std::shared_ptr<Namespace> getCurrentNS();
/// Lookup the namespace with the give name in the current context and
/// return a shared pointer to it or a `nullptr` in it doesn't exist.
std::shared_ptr<Namespace> getNS(llvm::StringRef ns_name);
SereneContext()
: pm(&mlirContext), targetPhase(CompilationPhase::NoOptimization) {
mlirContext.getOrLoadDialect<serene::slir::SereneDialect>();
mlirContext.getOrLoadDialect<mlir::StandardOpsDialect>();
// 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();
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, std::shared_ptr<Namespace>> 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
std::unique_ptr<SereneContext> makeSereneContext();
}; // namespace serene
#endif

View File

@ -0,0 +1,73 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SERENE_ENVIRONMENT_H
#define SERENE_ENVIRONMENT_H
#include "serene/llvm/patches.h"
#include <llvm/ADT/DenseMap.h>
#include <mlir/Support/LogicalResult.h>
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 K, typename V>
class Environment {
Environment<K, V> *parent;
// The actual bindings storage
llvm::DenseMap<K, V> pairs;
public:
Environment() : parent(nullptr) {}
Environment(Environment *parent) : parent(parent){};
/// Look up the given `key` in the environment and return it.
llvm::Optional<V> lookup(K key) {
if (auto value = pairs.lookup(key)) {
return value;
}
if (parent) {
return parent->lookup(key);
}
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(K key, V value) {
pairs.insert(std::pair<K, V>(key, value));
return mlir::success();
};
};
} // namespace serene
#endif

31
include/serene/errors.h Normal file
View File

@ -0,0 +1,31 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SERENE_ERRORS_H
#define SERENE_ERRORS_H
#include "serene/errors/errc.h"
#include "serene/errors/error.h"
#endif

View File

@ -0,0 +1,85 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SERENE_ERRORS_CONSTANTS_H
#define SERENE_ERRORS_CONSTANTS_H
#include <map>
#include <string>
namespace serene {
namespace errors {
enum ErrID {
E0000,
E0001,
E0002,
E0003,
E0004,
E0005,
E0006,
E0007,
};
struct ErrorVariant {
ErrID id;
std::string description;
std::string longDescription;
ErrorVariant(ErrID id, std::string desc, std::string longDesc)
: id(id), description(desc), longDescription(longDesc){};
};
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 std::map<ErrID, ErrorVariant *> ErrDesc = {
{E0000, &UnknownError}, {E0001, &DefExpectSymbol},
{E0002, &DefWrongNumberOfArgs}, {E0003, &FnNoArgsList},
{E0004, &FnArgsMustBeList}, {E0005, &CantResolveSymbol},
{E0006, &DontKnowHowToCallNode}, {E0007, &PassFailureError}};
} // namespace errors
} // namespace serene
#endif

View File

@ -0,0 +1,83 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#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,68 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SERENE_ERRORS_ERROR_H
#define SERENE_ERRORS_ERROR_H
#include "serene/context.h"
#include "serene/errors/constants.h"
#include "serene/errors/traits.h"
#include "serene/reader/location.h"
#include "serene/reader/traits.h"
#include "serene/traits.h"
//#include "serene/exprs/expression.h"
#include "llvm/Support/Error.h"
namespace serene::errors {
/// This enum represent the expression type and **not** the value type.
enum class ErrType {
Syntax,
Semantic,
Compile,
};
/// 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){};
std::string toString() const;
reader::LocationRange &where();
ErrorVariant *getVariant();
std::string getMessage();
~Error() = default;
};
}; // namespace serene::errors
#endif

View File

@ -0,0 +1,44 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef ERRORS_TRAITS_H
#define ERRORS_TRAITS_H
#include "serene/context.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,79 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef EXPRS_CALL_H
#define 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;
std::string toString() const;
MaybeNode analyze(SereneContext &);
void generateIR(serene::Namespace &, mlir::ModuleOp &){};
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,77 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef EXPRS_DEF_H
#define 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;
std::string toString() const;
MaybeNode analyze(SereneContext &);
void generateIR(serene::Namespace &, mlir::ModuleOp &);
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,153 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef EXPRS_EXPRESSION_H
#define EXPRS_EXPRESSION_H
#include "mlir/IR/BuiltinOps.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 <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 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 MaybeNode = Result<Node, ErrorTree>;
using Ast = std::vector<Node>;
using MaybeAst = Result<Ast, 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, ErrorTree> makeSuccessfulNode(Args &&...args) {
return Result<Node, 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 creating from passing
/// any argument to this function to the `serene::errors::Error` constructor.
template <typename T, typename... Args>
Result<T, ErrorTree> makeErrorful(Args &&...args) {
std::vector<ErrorPtr> v{
std::move(makeAndCast<errors::Error>(std::forward<Args>(args)...))};
return Result<T, ErrorTree>::error(v);
};
/// Convert the given AST to string by calling the `toString` method
/// of each node.
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

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

@ -0,0 +1,83 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef EXPRS_FN_H
#define 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;
std::string toString() const;
MaybeNode analyze(SereneContext &);
void generateIR(serene::Namespace &, mlir::ModuleOp &);
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,91 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef EXPRS_LIST_H
#define 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;
std::string toString() const;
void append(Node);
size_t count() const;
Ast from(uint begin);
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 &);
void generateIR(serene::Namespace &, mlir::ModuleOp &){};
~List() = default;
static bool classof(const Expression *e);
};
} // namespace exprs
} // namespace serene
#endif

View File

@ -0,0 +1,70 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef EXPRS_NUMBER_H
#define 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;
std::string toString() const;
MaybeNode analyze(SereneContext &ctx);
void generateIR(serene::Namespace &, mlir::ModuleOp &);
// TODO: This is horrible, we need to fix it after the mvp
int toI64();
~Number() = 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>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef EXPRS_SYMBOL_H
#define 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;
std::string toString() const;
MaybeNode analyze(SereneContext &);
void generateIR(serene::Namespace &, mlir::ModuleOp &){};
~Symbol() = default;
static bool classof(const Expression *e);
};
} // namespace exprs
} // namespace serene
#endif

View File

@ -0,0 +1,53 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef EXPRS_TRAITS_H
#define 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

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

@ -0,0 +1,166 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SERENE_JIT_H
#define SERENE_JIT_H
#include "serene/errors.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 <memory>
#include <mlir/Support/LLVM.h>
#define JIT_LOG(...) \
DEBUG_WITH_TYPE("JIT", llvm::dbgs() << "[JIT]: " << __VA_ARGS__ << "\n");
namespace serene {
class JIT;
using MaybeJIT = Result<std::unique_ptr<JIT>, serene::errors::Error>;
/// 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);
/// 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);
};
} // namespace serene
#endif

View File

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

View File

@ -0,0 +1,60 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SERENE_LLVM_PATCHES_H
#define SERENE_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(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(std::string LHS, std::string RHS) {
if (RHS == getEmptyKey())
return LHS == getEmptyKey();
if (RHS == getTombstoneKey())
return LHS == getTombstoneKey();
return LHS == RHS;
}
};
} // namespace llvm
#endif

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

@ -0,0 +1,128 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SERENE_NAMESPACE_H
#define SERENE_NAMESPACE_H
#include "serene/environment.h"
#include "serene/slir/generatable.h"
#include "serene/traits.h"
#include "serene/utils.h"
#include <algorithm>
#include <atomic>
#include <llvm/ADT/SmallString.h>
#include <llvm/ADT/StringRef.h>
#include <llvm/IR/Module.h>
#include <memory>
#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 <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
// TODO: replace the temporary `bool` by errors::Error
using MaybeModule = Result<std::unique_ptr<llvm::Module>, bool>;
// TODO: replace the temporary `bool` by errors::Error
using MaybeModuleOp = Result<mlir::OwningOpRef<mlir::ModuleOp>, bool>;
/// 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 Namespace {
private:
SereneContext &ctx;
bool initialized = false;
// 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
exprs::Ast tree;
public:
mlir::StringRef 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();
mlir::LogicalResult setTree(exprs::Ast &);
/// Increase the function counter by one
uint nextFnCounter();
SereneContext &getContext();
/// 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();
~Namespace();
};
/// 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
std::shared_ptr<Namespace>
makeNamespace(SereneContext &ctx, llvm::StringRef name,
llvm::Optional<llvm::StringRef> filename, bool setCurrent = true);
} // namespace serene
#endif

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

@ -0,0 +1,37 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SERENE_PASSES_H
#define SERENE_PASSES_H
#include <mlir/Pass/Pass.h>
namespace serene::passes {
std::unique_ptr<mlir::Pass> createSLIRLowerToAffinePass();
std::unique_ptr<mlir::Pass> createSLIRLowerToLLVMDialectPass();
} // namespace serene::passes
#endif

View File

@ -0,0 +1,65 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SERENE_READER_ERRORS_H
#define SERENE_READER_ERRORS_H
#include "serene/errors.h"
namespace serene {
namespace reader {
class ReadError : public std::exception {
private:
char *message;
public:
ReadError(char *msg) : message(msg){};
const char *what() const throw() { return message; }
};
class MissingFileError : public llvm::ErrorInfo<MissingFileError> {
using llvm::ErrorInfo<MissingFileError>::log;
using llvm::ErrorInfo<MissingFileError>::convertToErrorCode;
public:
static char ID;
std::string path;
// TODO: Move this to an error namespace somewhere.
int file_is_missing = int();
void log(llvm::raw_ostream &os) const {
os << "File does not exist: " << path << "\n";
}
MissingFileError(llvm::StringRef path) : path(path.str()){};
std::error_code convertToErrorCode() const {
return make_error_code(errc::no_such_file_or_directory);
}
};
} // namespace reader
} // namespace serene
#endif

View File

@ -0,0 +1,64 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef LOCATION_H
#define LOCATION_H
#include "mlir/IR/Location.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/OpDefinition.h"
#include <string>
namespace serene {
namespace reader {
/// It represents a location in the input string to the parser via `line`,
struct Location {
int pos; // Position of in the input string.
int line;
int col;
::std::string toString() const;
static Location unit() { return {0, 0, 0}; };
};
class LocationRange {
public:
Location start;
Location end;
LocationRange() : start(Location{0, 0, 0}), end(Location{0, 0, 0}){};
LocationRange(Location _start) : start(_start), end(_start){};
LocationRange(Location _start, Location _end) : start(_start), end(_end){};
LocationRange(const LocationRange &);
};
void incLocation(Location &, bool);
void decLocation(Location &, bool);
} // namespace reader
} // namespace serene
#endif

View File

@ -0,0 +1,111 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef READER_H
#define READER_H
#include "serene/errors.h"
#include "serene/exprs/expression.h"
#include "serene/exprs/list.h"
#include "serene/exprs/symbol.h"
#include "serene/reader/errors.h"
#include "serene/reader/location.h"
#include "serene/serene.h"
#include <llvm/Support/Debug.h>
#include <llvm/Support/raw_ostream.h>
#include <memory>
#include <sstream>
#include <stdexcept>
#include <string>
#include <system_error>
#include <vector>
#define READER_LOG(...) \
DEBUG_WITH_TYPE("READER", llvm::dbgs() \
<< "[READER]: " << __VA_ARGS__ << "\n");
namespace serene::reader {
/// Base reader class which reads from a string directly.
class Reader {
private:
char current_char = ';'; // Some arbitary char to begin with
std::stringstream input_stream;
Location current_location{0, 0, 0};
/// Returns the next character from the stream.
/// @param skip_whitespace An indicator to whether skip white space like chars
/// or not
char getChar(bool skip_whitespace);
/// Unreads the current character by moving the char pointer to the previous
/// char.
void ungetChar();
/// Returns a boolean indicating whether the given input character is valid
/// for an identifier or not.
bool isValidForIdentifier(char c);
// The property to store the ast tree
exprs::Ast ast;
exprs::Node readSymbol();
exprs::Node readNumber(bool);
exprs::Node readList();
exprs::Node readExpr();
public:
Reader() : input_stream(""){};
Reader(const llvm::StringRef string);
void setInput(const llvm::StringRef string);
/// Parses the the input and creates a possible AST out of it or errors
/// otherwise.
Result<exprs::Ast> read();
~Reader();
};
/// A reader to read the content of a file as AST
class FileReader {
std::string file;
Reader *reader;
public:
FileReader(const std::string file_name)
: file(file_name), reader(new Reader()) {}
Result<exprs::Ast> read();
~FileReader();
};
/// Parses the given `input` string and returns a `Result<ast>`
/// which may contains an AST or an `llvm::Error`
Result<exprs::Ast> read(llvm::StringRef input);
} // namespace serene::reader
#endif

View File

@ -0,0 +1,49 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef READER_SEMANTICS_H
#define 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<exprs::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 &tree);
}; // namespace serene::reader
#endif

View File

@ -0,0 +1,46 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef READER_TRAITS_H
#define 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

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

@ -0,0 +1,33 @@
/*
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SERENE_H
#define SERENE_H
// Sometimes we need this to make both analyzer happy
// and the fn signature right.
#define UNUSED(x) (void)(x)
namespace serene {}
#endif

View File

@ -0,0 +1,8 @@
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,43 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SERENE_SLIR_DIALECT_H_
#define SERENE_SLIR_DIALECT_H_
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/Dialect.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
#include "mlir/Interfaces/ControlFlowInterfaces.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 // 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,126 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#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

@ -0,0 +1,40 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SERENE_SLIR_H
#define SERENE_SLIR_H
#include "serene/exprs/expression.h"
#include <memory>
#include <mlir/IR/BuiltinOps.h>
#include <mlir/IR/MLIRContext.h>
namespace serene {
namespace slir {
std::unique_ptr<llvm::Module> compileToLLVMIR(serene::SereneContext &ctx,
mlir::ModuleOp &module);
} // namespace slir
} // namespace serene
#endif

View File

@ -0,0 +1,45 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SERENE_SLIR_UTILS_H
#define SERENE_SLIR_UTILS_H
#include "mlir/IR/BuiltinOps.h"
#include "serene/reader/location.h"
namespace serene {
class Namespace;
}
namespace serene::slir {
/**
* Convert a Serene location to MLIR FileLineLoc Location
*/
::mlir::Location toMLIRLocation(serene::Namespace &,
serene::reader::Location &);
} // namespace serene::slir
#endif

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

@ -0,0 +1,128 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* 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

@ -0,0 +1,28 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef TRAITS_LOCATABLE_H
#define TRAITS_LOCATABLE_H
#endif

View File

@ -0,0 +1,41 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SERENE_TYPES_TYPE_H
#define SERENE_TYPES_TYPE_H
#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

124
include/serene/utils.h Normal file
View File

@ -0,0 +1,124 @@
/* -*- C++ -*-
* Serene programming language.
*
* Copyright (c) 2019-2021 Sameer Rahmani <lxsameer@gnu.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SERENE_UTILS_H
#define SERENE_UTILS_H
#include "llvm/Support/Error.h"
#include <variant>
// C++17 required. We can't go back to 14 any more :))
namespace serene {
/// A similar type to Rust's Result data structure. It either holds a value of
/// type `T` successfully or holds a value of type `E` errorfully. It is
/// designed to be used in situations which the return value of a function might
/// contains some errors. The official way to use this type is to use the
/// factory functions `Success` and `Error`. For example:
///
/// \code
/// auto successfulResult = Result<int>::success(3);
/// auto notOkResult = Result<int>::error(SomeLLVMError());
// \endcode
///
/// In order check for a value being errorful or successful checkout the `ok`
/// method or simply use the value as a conditiona.
template <typename T, typename E = llvm::Error>
class Result {
// The actual data container
std::variant<T, E> contents;
/// The main constructor which we made private to avoid ambiguousness in
/// input type. `Success` and `Error` call this ctor.
template <typename InPlace, typename Content>
Result(InPlace i, Content &&c) : contents(i, std::forward<Content>(c)){};
public:
/// Create a succesfull result with the given value of type `T`.
static Result success(T v) {
return Result(std::in_place_index_t<0>(), std::move(v));
}
/// Create an errorful result with the given value of type `E` (default
/// `llvm::Error`).
static Result error(E e) {
return Result(std::in_place_index_t<1>(), std::move(e));
}
/// Return the value if it's successful otherwise throw an error
T &&getValue() && { return std::move(std::get<0>(contents)); };
/// Return the error value if it's errorful otherwise throw an error
E &&getError() && { return std::move(std::get<1>(contents)); };
// using std::get, it'll throw if contents doesn't contain what you ask for
/// Return the value if it's successful otherwise throw an error
T &getValue() & { return std::get<0>(contents); };
/// Return the error value if it's errorful otherwise throw an error
E &getError() & { return std::get<1>(contents); };
const T &getValue() const & { return std::get<0>(contents); }
const E &getError() const & { return std::get<1>(contents); }
/// Return the a boolean value indicating whether the value is succesful
/// or errorful.
bool ok() const { return std::holds_alternative<T>(contents); };
operator bool() const { return ok(); }
const T &getValueOrFail(llvm::StringRef msg, int exitCode = 1) const & {
if (ok()) {
return getValue();
}
llvm::errs() << msg << "\n";
exit(exitCode);
}
T &getValueOrFail(llvm::StringRef msg, int exitCode = 1) & {
if (ok()) {
return getValue();
}
llvm::errs() << msg << "\n";
exit(exitCode);
}
T &&getValueOrFail(llvm::StringRef msg, int exitCode = 1) && {
if (ok()) {
return std::move(getValue());
}
llvm::errs() << msg << "\n";
exit(exitCode);
}
};
} // 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

@ -1,122 +0,0 @@
;;; serene-dev --- Serene's development lib for Emacs users -*- lexical-binding: t; -*-
;;
;; Copyright (c) 2019-2024 Sameer Rahmani
;;
;; Author: Sameer Rahmani <lxsameer@gnu.org>
;; URL: https://serene-lang.org
;; Version: 0.1.0
;; Package-Requires: (projectile)
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;
;;; Commentary:
;; In order to use this library just put it somewhere that Emacs can load it
;; either via `require' or `load' and then call `serene/setup-dev-env' in your
;; init file.
;;
;; Keybindings:
;; * `s-c c' Runs `./builder compile'
;; * `s-c b' Runs `./builder build'
;;
;;; Code:
(defvar serene/compile-buffer "*compile*")
(defmacro serene/builder (command &optional buf-name sync)
"Run the given COMMAND via the builder script.
Use the optional BUF-NAME as the buffer.
If SYNC is non-nil it will block."
(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))))
(defun serene/compile (&optional sync)
"Compile the project.
It will run the `./builder compile' asynchronously or synchronously if
SYNC is non-nil."
(interactive)
(serene/builder "compile" serene/compile-buffer sync))
(defun serene/build ()
"Compile the project.
It will run the `./builder build' asynchronously."
(interactive)
(serene/builder "build" serene/compile-buffer))
(defun serene/build-release ()
"Compile the project.
It will run the `./builder build-release' asynchronously."
(interactive)
(serene/builder "build-release" serene/compile-buffer))
(defun serene/run (args)
"Run the project with the give ARGS.
It will run the `./builder build-release' asynchronously."
(interactive "sRun: ")
(serene/builder (format "run %s" args) serene/compile-buffer))
(defun serene/run-hello-world (args)
"Run the project with the give ARGS.
It will run the `./builder build-release' asynchronously."
(interactive "s-b . -l `pwd` docs.examples.hello_world ")
(let ((cmd (format "run -b . -l `pwd` docs.examples.hello_world %s" args)))
(serene/builder cmd serene/compile-buffer)))
(defun serene/run-hello-world-emit (args)
"Run the project with the give ARGS.
It will run the `./builder build-release' asynchronously."
(interactive (list (completing-read "Emit: " '("ast" "semantic" "slir" "mlir" "lir" "ir" "jit" "object" "target"))))
(let ((cmd (format "run -b . -l `pwd` docs.examples.hello_world -emit %s" args)))
(serene/builder cmd serene/compile-buffer)))
(defun serene/setup-keybindings ()
"Setup the serene-dev keybindings."
(interactive)
(define-key c++-mode-map (kbd "s-c c") #'serene/compile)
(define-key c++-mode-map (kbd "s-c b") #'serene/build)
(define-key c++-mode-map (kbd "s-c r") #'serene/run)
(define-key c++-mode-map (kbd "s-c e") #'serene/run-hello-world-emit))
(defun serene/format-buffer ()
"Format the buffer if `lsp-format-buffer' is available."
(when (and (eq major-mode 'c++-mode) (featurep 'lsp-mode))
(lsp-format-buffer)))
(defun serene/setup-dev-env ()
"Setup the development env of Serene."
(interactive)
(add-hook 'c++-mode-hook
(lambda ()
(require 'projectile)
(serene/setup-keybindings)
(add-hook 'before-save-hook #'serene/format-buffer))))
(provide 'serene-dev)
;;; serene-dev.el ends here

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

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