seanbaxter / circle Goto Github PK
View Code? Open in Web Editor NEWThe compiler is available for download. Get it!
Home Page: http://www.circle-lang.org/
The compiler is available for download. Get it!
Home Page: http://www.circle-lang.org/
The program:
#include <initializer_list>
struct lattice
{
template<class Size1, class Size2>
explicit lattice(const Size1& dimension1, const Size2& dimension2){}
template<class Size>
lattice(std::initializer_list<Size> dimensions){}
};
int main()
{
// XXX this should choose the second constructor
lattice l = {2, 2};
return 0;
}
Causes circle to emit the following error message:
$ ~/Desktop/circle/circle -I. repro.cpp
error: repro.cpp:17:13
explicit constructor chosen in copy-list-initialization
lattice l = {2, 2};
clang & g++ compile the program without error.
Compiler details:
$ circle --version ; echo ; clang --version ; echo ; g++ --version
circle version 1.0.0-135
Circle public preview build 135
Built Sep 26 2021 22:32:16
(c) 2021 Sean Baxter
https://www.circle-lang.org/
Twitter: @seanbax
clang version 10.0.0-4ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Hi,
just noticed on twitter your circle 100 release with graphics shader C++ support..
seems you only ship
is this project buildable on Windows? i.e. has Windows support?
in case yes.. better yet.. can you provide Windows prebuilt binaries (circle.exe)?
thanks..
nvcc
automatically links against libcudart
when building an executable from a CUDA source file. For compatibility with legacy CUDA builds, it would be helpful if circle also behaved this way.
circle_latest is build_125; 1 build behind build_126.
16728K build_125.tgz
16732K build_126.tgz
16728K circle_latest.tgz
#include <cstdio>
template<class T>
struct child {
~child() {
@meta std::printf("Never called\n");
}
};
template<class T>
child<T> dep = {};
static_assert(sizeof(dep<int>));
First: circle is incredible! I'm amazed by the many ways it significantly improves upon conventional C++.
It looks like bitfield members work properly in circle, but the introspection tools (e.g. @member_count
) for them do not:
#include <cstdio>
struct data_t {
uint32_t foo : 7;
uint32_t bar : 2;
uint32_t baz : 13;
uint32_t qux : 10;
};
struct nonbitfield_data_t {
uint32_t foo;
uint32_t bar;
uint32_t baz;
uint32_t qux;
};
template<typename type_t>
void print_members() {
printf("%s has %i members:\n", @type_string(type_t), @member_count(type_t));
printf("%d: %s - %s\n", int..., @member_type_strings(type_t),
@member_names(type_t))...;
}
int main() {
static_assert(sizeof(data_t) == 4);
print_members<data_t>();
printf("\n");
print_members<nonbitfield_data_t>();
}
/* output:
data_t has 0 members:
nonbitfield_data_t has 4 members:
0: uint32_t - foo
1: uint32_t - bar
2: uint32_t - baz
3: uint32_t - qux
*/
working example: https://godbolt.org/z/j6o1jsGGY
testing done locally on ubuntu 20.04 with build_136
Something goes wrong when I try to execute mandelbrot
function at compile time.
It is related to <complex>
. Compiler does not output any helpful message.
./circle mandelbrot.cxx
Segmentation fault
This is expected output with handcrafted complex
class.
This is how it run with std::complex<>
.
mandelbrot.cxx
/// Adapted from wes' code. <https://web.archive.org/web/20210411041036/http://www.fractalforums.com/programming/mandelbrot-with-only-18-lines-of-cplusplus-code!/>
#include <cstdio>
#include <complex>
static void mandelbrot()
{
using namespace std;
constexpr auto kRows = 22, kCols = 78, kRuns = 20;
for (float x: @range(kRows + 1)...)
{
for (float y: @range(kCols - 1)...)
{
complex<float> z, c { y * 2 / kCols - 1.5f, x * 2 / kRows - 1.0f };
auto i = 0;
while (abs(z) < 2 and ++i < kRuns)
z = pow(z, 2.0f) + c;
putchar(i != kRuns ? '.' : '#');
}
putchar('\n');
}
}
int main()
{
@meta mandelbrot();
mandelbrot();
}
Running on Linux 5.6.4-arch1-1 with a freshly cloned repo
$ build_96/circle circle/examples/eprintf/eprintf.cxx
Segmentation fault (core dumped)
I would try to debug a bit, but alas... no debug symbols in the compiler.
The program
#include <cuda_runtime_api.h>
#include <iostream>
#include <utility>
#define EXEC_CHECK_DISABLE #pragma nv_exec_check_disable
EXEC_CHECK_DISABLE
template<class F>
__host__ __device__ auto invoke(F&& f)
{
return std::forward<F>(f)();
}
__global__ void kernel()
{
invoke([]
{
printf("invoke called from __device__\n");
});
}
int main()
{
invoke([]
{
std::cout << "invoke called from __host__" << std::endl;
});
kernel<<<1,1>>>();
cudaDeviceSynchronize();
std::cout << "OK" << std::endl;
return 0;
}
Causes circle to emit the following error message
$ circle --cuda-path=/usr/local/cuda -sm_50 repro.cu -lcudart
preprocessor: repro.cu:7:1
unexpected # in token stream
Compiler details:
$ circle --version
circle version 1.0.0-136
Circle public preview build 136
Built Sep 27 2021 23:42:52
(c) 2021 Sean Baxter
https://www.circle-lang.org/
Twitter: @seanbax
Dcoumentation refers to sanity.cxx which is not included in the download.
Is there any reason a subset of Circle cannot output valid C code? Perhaps a meta_c@ to emit compile-time evaluations that are correct C? Probably need this anyway for metas that must be in older C++ versions or avoid the use of the STL.
Probably quickest to blast test suite code with clang to see if there are errors and if so pass through clangAST to describe known C++ AST elements that are illegal in C?
When I ported Ruby 1.8 to Blue Gene/L, having the test suite was 100x more helpful than the documentation. You might consider opening an integration test suite, https://www.cs.princeton.edu/courses/archive/spring01/cs333/awktest.html
The program
#include <type_traits>
struct dispatch_foo
{
// XXX crashes
template<class T,
typename std::enable_if<!std::is_arithmetic<T&&>::value>::type* = nullptr
>
constexpr auto operator()(T&&) const
-> decltype(operator()<T>())
{
return operator()<T>();
}
// // XXX doesn't crash
// template<class T,
// class = std::enable_if_t<!std::is_arithmetic<T&&>::value>
// >
// constexpr auto operator()(T&&) const
// -> decltype(operator()<T>())
// {
// return operator()<T>();
// }
};
constexpr const dispatch_foo foo;
void main()
{
foo(13);
}
Causes a segmentation fault when compiled with circle:
$ /home/jhoberock/Desktop/circle/circle -std=c++17 segmentation_fault.cpp
Segmentation fault (core dumped)
An alternative spelling of the SFINAE guard correctly produces a compiler error.
Compiler details:
$ /home/jhoberock/Desktop/circle/circle --version
circle version 1.0.0-134
Circle public preview build 134
Built Sep 25 2021 16:55:11
(c) 2021 Sean Baxter
https://www.circle-lang.org/
Twitter: @seanbax
I get the error(?)
preprocessor: libtorch/include/c10/util/Flags.h:173:1
token-pasting operation does not yield a token
while trying to include libtorch. Steps to reproduce: Download libtorch from https://pytorch.org/get-started/locally/, unpack and then
circle -I=libtorch/include/ libtorch/include/c10/util/Flags.hpp
yields the error.
I downloaded your build_81. Your circle executable there required libffi.so.6. On my Centos 6 + x86_64 system, I have libffi .so.5, so circle no workee.
Then low and behold trying to build libffi downloaded from github is a big fail.
Your concept for circle is very appealing. But you need to open it up somehow so folks like me can actually try to use it.
Thanks for your efforts. I hope they are successful because circle does look like a good idea. In fact, the peglib thing is what got me to look at it. I wish it worked for me right out of the box, because then I'd probably be spending lots of time thinking about the possibilities.
I may come back after some time passes and check out your progress.
I just heard about Circle on cppcast and I must say I'm impressed. I hope It's not going to sound too much like I'm a know-it-all, but I'm going to suggest a change in business model. I don't know all the facts and I may get some things wrong, but I wanted to write this anyway, because I may have some ideas you can use.
The problem currently is that it's closed source and it could disappear any day, so I don't think people will take it seriously (I for sure wouldn't use it for commercial projects right now). I know it's a chicken and egg problem though (you may not get funding if you release the source).
Idea 1:
Why not make implementation open-source, build a community of users and then make money on consulting? It looks a bit like you are trying to repeat what Bjarne Stroustrup did, but it's not the 1980s anymore.
Or maybe make the main language open-source and keep some tools (a non-essential one like a performance analyzer) paid?
Idea 2
In any case, I think you can learn a lot from the story of the D programming language. It is slowly gaining traction but its future is unclear because it has it's complications and it's not a big enough improvement over C++. An example of such feature is compile-time regex, but this is not important enough to make people switch languages.
A way for Circle to grow could be by creating a unique use case that could not be done easily in C++. Maybe see what Halide (https://halide-lang.org/) does, and see if you can replicate some or all of that with the compile-time magic of Circle. That could make you the king of HPC.
Idea 3
One of the historical problems of D was a closed-source implementation. Some people just didn't want to work with such a tool. Also, even after open-sourcing it, the level of community contribution to the language itself was very small until the implementation began being hosted on Github. This is really important. There is always GNU GPL licence to use if you want to restrict commercial uses somewhat but I'm not sure how it would influence the behavior of the people you are pitching the language to.
Can circle output C++ code?
The docker file provided at https://www.circle-lang.org/Dockerfile is not valid.
Dockerfile as downloaded:
FROM ubuntu:18.04
MAINTAINER Sean <[email protected]>
RUN apt-get update && \
apt-get install -y binutils libstdc++-8-dev wget git && \
wget -P /home https://www.circle-lang.org/debian/build_97.tgz && \
tar xvf /home/build_98.tgz -C /usr/bin && \
chmod +x /usr/bin/circle && \
git clone https://www.github.com/seanbaxter/circle /home/circle_docs
Output:
$ docker build --tag=circle_docker .
Sending build context to Docker daemon 2.048kB
Step 1/3 : FROM ubuntu:18.04
[...]
done
--2020-06-07 13:15:03-- https://www.circle-lang.org/debian/build_97.tgz
Resolving www.circle-lang.org (www.circle-lang.org)... 64.90.37.113
Connecting to www.circle-lang.org (www.circle-lang.org)|64.90.37.113|:443... connected.
HTTP request sent, awaiting response... 404 Not Found
2020-06-07 13:15:04 ERROR 404: Not Found.
The command '/bin/sh -c apt-get update && apt-get install -y binutils libstdc++-8-dev wget git && wget -P /home https://www.circle-lang.org/debian/build_97.tgz && tar xvf /home/build_98.tgz -C /u
Updated file to fix the URL: (https://www.circle-lang.org/debian/build_97.tgz -> https://www.circle-lang.org/linux/build_98.tgz)
FROM ubuntu:18.04
MAINTAINER Sean <[email protected]>
RUN apt-get update && \
apt-get install -y binutils libstdc++-8-dev wget git && \
wget -P /home https://www.circle-lang.org/linux/build_98.tgz && \
tar xvf /home/build_98.tgz -C /usr/bin && \
chmod +x /usr/bin/circle && \
git clone https://www.github.com/seanbaxter/circle /home/circle_docs
Output:
$ docker build --tag=circle_docker .
[...]
Successfully tagged circle_docker:latest
$ docker run -it circle_docker bash
# cd /home/circle_docs/examples/special
# circle special.cxx
circle: error while loading shared libraries: libelf.so.1: cannot open shared object file: No such file or directory
Updated file to install libelf-dev
FROM ubuntu:18.04
MAINTAINER Sean <[email protected]>
RUN apt-get update && \
apt-get install -y binutils libstdc++-8-dev libelf-dev wget git && \
wget -P /home https://www.circle-lang.org/linux/build_98.tgz && \
tar xvf /home/build_98.tgz -C /usr/bin && \
chmod +x /usr/bin/circle && \
git clone https://www.github.com/seanbaxter/circle /home/circle_docs
Output:
$ docker build --tag=circle_docker .
[...]
Successfully tagged circle_docker:latest
$ docker run -it circle_docker bash
# cd /home/circle_docs/examples/special
# circle special.cxx
circle: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.26' not found (required by circle)
Updated file to install a newer version of libstdc++ (libstdc++-9-dev
). This requires a newer version of Ubuntu (20.04
)
FROM ubuntu:20.04
MAINTAINER Sean <[email protected]>
RUN apt-get update && \
apt-get install -y binutils libstdc++-9-dev libelf-dev wget git && \
wget -P /home https://www.circle-lang.org/linux/build_98.tgz && \
tar xvf /home/build_98.tgz -C /usr/bin && \
chmod +x /usr/bin/circle && \
git clone https://www.github.com/seanbaxter/circle /home/circle_docs
Output:
$ docker build --tag=circle_docker .
[...]
Successfully tagged circle_docker:latest
$ docker run -it circle_docker bash
# cd /home/circle_docs/examples/special
# circle special.cxx
Generating code for function 'E1'
note: first Einstein special function
Injecting expression 'sq(x) * exp(x) / sq(exp(x) - 1)'
Injecting Taylor series
Generating code for function 'factorial'
Injecting statements 'double y = 1; while(x > 1) y *= x--; return y;'
Generating code for function 'sigmoid'
Injecting expression '1 / (1 + exp(-x))'
Injecting Taylor series
Generating code for function 'sin'
Injecting expression 'sin(x)'
Injecting Taylor series
Generating code for function 'tanh'
Injecting expression 'tanh(x)'
Injecting Taylor series
error: /usr/include/string.h:73:20
cannot overload void* memchr(const void*, int, unsigned long) noexcept on return type
previous declaration at <implicit declaration>
extern const void *memchr (const void *__s, int __c, size_t __n)
^
error: /usr/include/string.h:208:20
cannot overload char* strchr(const char*, int) noexcept on return type
previous declaration at <implicit declaration>
extern const char *strchr (const char *__s, int __c)
^
error: /usr/include/string.h:312:20
cannot overload char* strstr(const char*, const char*) noexcept on return type
previous declaration at <implicit declaration>
extern const char *strstr (const char *__haystack, const char *__needle)
^
Example program:
#include <string>
#include <cstring>
int main() {
return 0;
}
Output:
# circle test.cxx
error: /usr/include/string.h:73:20
cannot overload void* memchr(const void*, int, unsigned long) noexcept on return type
previous declaration at <implicit declaration>
extern const void *memchr (const void *__s, int __c, size_t __n)
^
error: /usr/include/string.h:208:20
cannot overload char* strchr(const char*, int) noexcept on return type
previous declaration at <implicit declaration>
extern const char *strchr (const char *__s, int __c)
^
error: /usr/include/string.h:312:20
cannot overload char* strstr(const char*, const char*) noexcept on return type
previous declaration at <implicit declaration>
extern const char *strstr (const char *__haystack, const char *__needle)
^
The program
#include <concepts>
#include <compare>
struct foo
{
auto operator<=>(const foo&) const = default;
};
struct bar
{
bool operator==(const bar&) const
{
return true;
}
};
int main()
{
static_assert(std::equality_comparable<foo>);
static_assert(std::equality_comparable<bar>);
}
Causes circle to emit the error
$ circle -std=c++20 repro.cpp
error: repro.cpp:19:3
static_assert failed
static_assert(std::equality_comparable<foo>);
^
error: translation aborted; too many errors
clang correctly compiles this program.
Compiler details:
$ circle --version ; echo ; clang --version
circle version 1.0.0-137
Circle public preview build 137
Built Oct 7 2021 23:28:38
(c) 2021 Sean Baxter
https://www.circle-lang.org/
Twitter: @seanbax
clang version 10.0.0-4ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
When compiled with circle, the program:
#include <type_traits>
# define CONCATENATE_IMPL(x, y) x##y
# define CONCATENATE(x, y) CONCATENATE_IMPL(x, y)
# define MAKE_UNIQUE(x) CONCATENATE(x, __COUNTER__)
# define REQUIRES_IMPL(unique_name, ...) bool unique_name = true, typename std::enable_if<(unique_name and __VA_ARGS__)>::type* = nullptr
# define REQUIRES(...) REQUIRES_IMPL(MAKE_UNIQUE(__deduced_true), __VA_ARGS__)
struct foo
{
template<class T,
REQUIRES(std::is_arithmetic<T>::value)
>
void bar();
};
int main()
{
}
Produces the following compilation error message:
$ circle -std=c++17 repro.cpp
error: repro.cpp:17:12
undeclared identifier '__deduced_true1'
REQUIRES(std::is_arithmetic<T>::value)
^
Compiler details:
$ circle --version
circle version 1.0.0-132
Circle public preview build 132
Built Sep 20 2021 18:12:19
(c) 2021 Sean Baxter
https://www.circle-lang.org/
Twitter: @seanbax
Hey @thedmd, is it possible to upgrade the godbolt circle to libstdc++10? I'm not sure why it is only finding 9. I've tried -libstdc++=10 which fails.
The program
__managed__ int result;
int main()
{
return 0;
}
Causes circle to emit the error message
$ circle --cuda-path=/usr/local/cuda -sm_50 repro.cu
error: repro.cu:1:17
unsupported attribute on declaration
__managed__ int result;
^
Compiler details:
$ ~/Desktop/circle/circle --version
circle version 1.0.0-136
Circle public preview build 136
Built Sep 27 2021 23:42:52
(c) 2021 Sean Baxter
https://www.circle-lang.org/
Twitter: @seanbax
#pragma nv_exec_check_disable
allows users to write __host__ __device__
function templates that call either __host__
or __device__
functions in their definitions.
I understand that circle's execution space inference makes such functionality obsolete, but support for this pragma would be appreciated to make legacy codebases work.
The program
#include <future>
int main()
{
std::promise<int> p;
p.get_future();
return 0;
}
Causes circle to emit the error message:
$ ~/Desktop/circle/circle repro.cpp
ODR used by: int main()
repro.cpp:6:15
p.get_future();
^
ODR used by: std::future<int> std::promise<int>::get_future()
/usr/include/c++/9/future:1105:28
{ return future<_Res>(_M_future); }
^
ODR used by: std::future<int>::future(const std::shared_ptr<std::__future_base::_State_baseV2>&)
/usr/include/c++/9/future:773:45
future(const __state_type& __state) : _Base_type(__state) { }
^
ODR used by: std::__basic_future<int>::__basic_future(const std::shared_ptr<std::__future_base::_State_baseV2>&)
/usr/include/c++/9/future:733:40
_M_state->_M_set_retrieved_flag();
^
ODR used by: void std::__future_base::_State_baseV2::_M_set_retrieved_flag()
/usr/include/c++/9/future:454:32
if (_M_retrieved.test_and_set())
^
error: /usr/include/c++/9/bits/atomic_base.h:195:36
... included from /usr/include/c++/9/bits/shared_ptr_atomic.h:33:10
... included from /usr/include/c++/9/memory:82:12
... included from /usr/include/c++/9/thread:39:10
... included from /usr/include/c++/9/future:39:10
... included from repro.cpp:1:10
cg: bool __atomic_test_and_set(volatile void*, int) noexcept not implemented
return __atomic_test_and_set (&_M_i, int(__m));
Compiler details:
$ ~/Desktop/circle/circle --version
circle version 1.0.0-136
Circle public preview build 136
Built Sep 27 2021 11:04:48
(c) 2021 Sean Baxter
https://www.circle-lang.org/
Twitter: @seanbax
The program
template<class T>
struct noncopyable
{
T x;
noncopyable(const noncopyable&) = delete;
};
int main()
{
noncopyable<int> x{13};
return 0;
}
Causes circle to emit the following error message:
$ circle repro.cpp
error: repro.cpp:12:22
cannot convert prvalue int to const noncopyable<int>&
noncopyable<int> x{13};
Compiler details:
$ ~/Desktop/circle/circle --version
circle version 1.0.0-136
Circle public preview build 136
Built Sep 27 2021 11:04:48
(c) 2021 Sean Baxter
https://www.circle-lang.org/
Twitter: @seanbax
circle (build 93) segfaults when compiling the following program with -g.
// test.cc
#include <iostream>
#include "nlohmann/json.hpp"
using json = nlohmann::json;
int main() {
json j = "hi there!";
std::cout << j;
return 0;
}
code was compiled with circle test.cc -Ipath/to/nlohmann/json/include -g
, using g++ produces no error.
The program
int main()
{
auto device_lambda = [] __device__ () {};
return 0;
}
Causes circle to emit the error message
$ circle --cuda-path=/usr/local/cuda -sm_50 repro.cu
error: repro.cu:3:24
error forming list comprehension
auto device_lambda = [] __device__ () {};
^
error: repro.cu:3:25
expected 1 or more items in initializer-list
auto device_lambda = [] __device__ () {};
Compiler details:
$ ~/Desktop/circle/circle --version
circle version 1.0.0-136
Circle public preview build 136
Built Sep 27 2021 23:42:52
(c) 2021 Sean Baxter
https://www.circle-lang.org/
Twitter: @seanbax
Hi, I'm interested in using circle's metaprogramming tools to extend an existing codebase that makes use of SIMD intrinsics, but it seems to be failing to compile. A small example here (code below)
#include <immintrin.h>
struct vec4 {
double values[4];
double & operator()(int i) { return values[i]; }
const double & operator()(int i) const { return values[i]; }
};
vec4 plus(const vec4 & x, const vec4 & y) {
return vec4{x(0) + y(0), x(1) + y(1), x(2) + y(2), x(3) + y(3)};
}
vec4 operator+(const vec4 & x, const vec4 & y) {
__m256d _x = _mm256_loadu_pd(x.values);
__m256d _y = _mm256_loadu_pd(y.values);
vec4 sum;
_mm256_storeu_pd(sum.values, _mm256_add_pd(_x, _y));
return sum;
}
illustrates the problem: errors to the tune of
vector_size 64 is unsupported
typedef char __v64qi __attribute__ ((__vector_size__ (64)));
Meanwhile, the 128-bit intrinsics seem to compile successfully:
#include <xmmintrin.h>
struct vec2 {
double values[2];
double & operator()(int i) { return values[i]; }
const double & operator()(int i) const { return values[i]; }
};
vec2 plus(const vec2 & x, const vec2 & y) {
return vec2{x(0) + y(0), x(1) + y(1)};
}
vec2 operator+(const vec2 & x, const vec2 & y) {
__m128d _x = _mm_loadu_pd(x.values);
__m128d _y = _mm_loadu_pd(y.values);
vec2 sum;
_mm_storeu_pd(sum.values, _mm_add_pd(_x, _y));
return sum;
}
With gcc/clang, flags (e.g. -mavx
) are sometimes needed to enable the larger intrinsics, I was wondering if there is something similar that needs to be passed to circle
or if these are currently unsupported.
These examples were tested against build_136 on Ubuntu 20.04, as well as compiler explorer's "Latest" circle option (unsure what version that actually is).
I've something similar to Circle on my TODO list for ages to replace the preprocessor.
I feel like outputting C++ would be great as many projects can't use LLVM, video games and embedded come to mind.
Is it possible at all?
The program:
#include <array>
int main()
{
return 0;
}
Yields the following compiler error message:
$ ~/Desktop/circle/circle -std=c++14 repro.cpp
error: /usr/include/c++/9/array:245:29
... included from repro.cpp:1:10
undeclared identifier 'is_same_v'
-> array<enable_if_t<(is_same_v<_Tp, _Up> && ...), _Tp>,
I'm trying to use the latest compiler version (96), to compile example https://www.circle-lang.org/saxpy.html. I'm using ubuntu 18.04 and installed the cuda package version 10.2 from https://developer.nvidia.com/cuda-downloads.
circle -cuda-path /usr/local/cuda-10.2 -sm_35 -sm_52 -sm_61 -sm_70 saxpy.cu -lcudart
results in
error: cannot find function __cudaPopCallConfiguration in CUDA Toolkit
I ran
objdump -D /usr/local/cuda-10.2/lib64/libcudart.so | grep __cudaPopCallConfiguration
and this symbol seems to be present.
I hope project will find support (patreon, maybe?) or become opensource, otherwise it will be risky to use with big production code bases.
It looks simpler than http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0707r3.pdf
Hello @seanbaxter
Did you consider putting circle compiler on Compiler Explorer? That should boost visibility and allow people play with compiler more easily.
Your overall point, that you have write weird code to things at compile time, still stands, but I think a fair comparison against C++ would probably have the code look more like this:
#include <cstddef>
#include <cstdio>
#include <utility>
template<std::size_t first, std::size_t last, typename Function>
constexpr void unroll(Function && function) {
[&]<std::size_t... indexes>(std::index_sequence<indexes...>) {
(..., function(std::integral_constant<std::size_t, indexes + first>()));
}(std::make_index_sequence<last - first>());
}
template<int I>
void func(int & x) {
x *= 2;
printf("After I = %d, x = %d\n", I, x);
}
int main() {
int x = 1;
unroll<0, 5>([&](auto i) {
func<i.value>(x);
});
}
The unroll
code is pretty strange (because we do not yet have for...
), but it can at least be a reusable library function. Importantly, the usage side is much simpler: you can access the static constexpr member of an integral_constant
by just using normal member variable syntax. No need for a local enum and decltype.
The program
#include <type_traits>
struct dispatch_foo
{
template<class T,
class = std::enable_if_t<std::is_arithmetic<T>::value>
>
constexpr int operator()() const
{
return 0;
}
template<class T,
class = std::enable_if_t<std::is_reference<T&&>::value>
>
constexpr auto operator()(T&&) const
-> decltype(operator()<std::decay_t<T&&>>())
{
return operator()<std::decay_t<T&&>>();
}
};
template<class T>
using foo_t = decltype(dispatch_foo{}(std::declval<T>()));
int main()
{
foo_t<char> x;
return 0;
}
Generates the following error message when compiled with circle:
$ circle -I. -std=c++14 repro.cpp
error: repro.cpp:26:38
no viable candidates in call to 'operator()'
argument 0 is xvalue char
using foo_t = decltype(dispatch_foo{}(std::declval<T>()));
^
candidate: int dispatch_foo::operator()() const
repro.cpp:8:17
constexpr int operator()() const
^
error: invalid argument count
function expects 0 arguments
candidate: decltype(operator()<std::decay_t<T&&>>()) dispatch_foo::operator()(T&&) const
repro.cpp:17:18
constexpr auto operator()(T&&) const
^
instantiation: decltype(operator()<std::decay_t<T&&>>()) dispatch_foo::operator()(T&&) const
during substitution of return type of decltype(operator()<std::decay_t<T&&>>()) dispatch_foo::operator()(T&&) const
template arguments: [
'T' = char
'1' = void
]
repro.cpp:26:38
using foo_t = decltype(dispatch_foo{}(std::declval<T>()));
^
error: repro.cpp:18:46
call to member function int dispatch_foo::operator()() const without an object argument
function declared at repro.cpp:9:3
-> decltype(operator()<std::decay_t<T&&>>())
^
clang compiles this program without error:
$ clang -I. -std=c++14 repro.cpp
Compiler details:
$ circle --version
circle version 1.0.0-134
Circle public preview build 134
Built Sep 25 2021 16:55:11
(c) 2021 Sean Baxter
https://www.circle-lang.org/
Twitter: @seanbax
jhoberock@jhoberock-dt:~/dev/git/coord$ clang --version
clang version 10.0.0-4ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
One of the problems with C++ are the "incorrect" defaults (eg mutable variables by default instead of mutable when needed). One of these defaults is missing noexcept(condition)
on function bodies being evaluated as noexcept(false)
instead of automatically deducing based on the function's body. Consider the following example : judging by the body of f
, it is noexcept
, but the check decides it is rather noexcept(false)
(hence the program returns 0).
I propose the following changes:
Functions without noexcept
in their bodies are considered to be non-throwing whether the operations on the body of the functions are non-throwing, otherwise (if noexcept(cond)
is specified) the function is declared to throw whether the condition is false
. In cases of conditional branches (if
/while
) each branch contributes to the exception specification of the function, unless the branch is evaluated at compile-time (eg. on if constexpr
) in which only the chosen branch contributes (obviously). The same rules apply to lambdas and operator overloads.
These changes allow for more ergonomic and optimized code. Consider the following examples:
LIFT
macro#define LIFT(foo) \
[](auto&&... x) \
noexcept(noexcept(foo(std::forward<decltype(x)>(x)...))) \
-> decltype(foo(std::forward<decltype(x)>(x)...)) \
{ return foo(std::forward<decltype(x)>(x)...); }
With noexcept(auto)
#define LIFT(foo) \
[](auto&&... x) \
/* automatic deduction of exception guarantees */
-> decltype(foo(std::forward<decltype(x)>(x)...)) \
{ return foo(std::forward<decltype(x)>(x)...); }
This also applies to any other lambda object and/or function, allowing for a terser syntax.
constexpr vector& operator=( std::initializer_list<T> ilist ) noexcept(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value
|| std::allocator_traits<Allocator>::is_always_equal::value) { /* ... */ }
With noexcept(auto)
constexpr vector& operator=( std::initializer_list<T> ilist ) { /* ... */ }
As you may have noticed from the examples the feature allows for templated code that is both easier to write and maintain, making metaprogramming more approachable to a wider range of programmers. There are also other cases where the feature would be useful. For example, given the compiler will automatically deduce the exception specification, C functions can be assumed exception free leading to more optimizations.
PS: Please note that even though the feature name is noexcept(auto)
, there is no proposal to add such syntax. Instead, it refers to the ability of the compiler to deduce the exception specification of a function.
The following program
void foo(auto&&...){}
int main()
{
foo();
return 0;
}
Causes circle to emit the error message
$ circle -std=c++20 repro.cpp
error: repro.cpp:5:6
no viable candidates in call to 'foo'
foo();
^
candidate: void foo(0&&)
repro.cpp:1:6
void foo(auto&&...){}
^
error: invalid argument count
function expects 1 or more arguments
Clang and g++ accept the program:
$ clang -std=c++20 repro.cpp
$ g++ -std=c++2a -fconcepts repro.cpp
Compiler details:
$ circle --version ; echo ; clang --version ; echo ; g++ --version
circle version 1.0.0-137
Circle public preview build 137
Built Oct 7 2021 23:28:38
(c) 2021 Sean Baxter
https://www.circle-lang.org/
Twitter: @seanbax
clang version 10.0.0-4ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
I'm toying with circle in compiler-explorer and I'm looking for a way to emit Intel syntax assembly output.
I checked every corner of the docs I can find already, last thing I can do I to ask.
Is there a switch I can use to do that?
The program
template<class T>
struct has_member_template
{
template<class... Types>
using type = int;
};
template<class T, template<class...> class Template = has_member_template<T>::template type>
using foo_result_t = int;
template<class T>
foo_result_t<T> foo()
{
return {};
}
int main()
{
foo<int>();
return 0;
}
Causes a segmentation fault when compiled with circle:
$ ~/Desktop/circle/circle repro.cpp
Segmentation fault (core dumped)
Compiler details:
$ circle --version
circle version 1.0.0-136
Circle public preview build 136
Built Sep 27 2021 11:04:48
(c) 2021 Sean Baxter
https://www.circle-lang.org/
Twitter: @seanbax
For compatibility with legacy nvcc builds, it would be helpful if circle recognized nvcc command line options such as -arch.
The following program
template<class...>
struct not_a_member_template {};
template<class T>
struct foo
{
template<class... Types>
using member_template = int;
};
// XXX error
template<class T, template<class...> class Template = foo<T>::template member_template>
using bar = int;
// XXX compiles OK
template<class T, template<class...> class Template = not_a_member_template>
using bar = int;
int main()
{
return 0;
}
Causes circle to emit the following error message:
$ circle -I. repro.cpp
error: repro.cpp:13:55
expected a template as default of template-template parameter
template<class T, template<class...> class Template = foo<T>::template member_template>
Compiler details:
$ ~/Desktop/circle/circle --version
circle version 1.0.0-135
Circle public preview build 135
Built Sep 26 2021 22:32:16
(c) 2021 Sean Baxter
https://www.circle-lang.org/
Twitter: @seanbax
The following program:
#ifndef INCLUDE_LEVEL
# define INCLUDE_LEVEL 0
#else
# pragma push_macro("INCLUDE_LEVEL")
# define INCLUDE_LEVEL 1
#endif
// at this point the macro stack is:
//
// INCLUDE_LEVEL = 0
#ifndef INCLUDE_LEVEL
# define INCLUDE_LEVEL 0
#else
# pragma push_macro("INCLUDE_LEVEL")
# define INCLUDE_LEVEL 1
#endif
// at this point the macro stack is:
//
// INCLUDE_LEVEL = 1
// INCLUDE_LEVEL = 0
#if INCLUDE_LEVEL == 1
# pragma pop_macro("INCLUDE_LEVEL")
#else
# undef INCLUDE_LEVEL
#endif
// at this point the macro stack is:
//
// INCLUDE_LEVEL = 0
#if INCLUDE_LEVEL == 1
# pragma pop_macro("INCLUDE_LEVEL")
#else
# undef INCLUDE_LEVEL
#endif
// at this point the macro stack should be empty, and INCLUDE_LEVEL should not be defined
#ifdef INCLUDE_LEVEL
# error INCLUDE_LEVEL defined in client code.
#endif
int main()
{
return 0;
}
Causes circle to hit the #error
case:
$ circle -I. repro.cpp
preprocessor: repro.cpp:51:9
#error: 'INCLUDE_LEVEL defined in client code.'
clang compiles without error, but g++ complains about macro redefinition:
$ g++ -I. repro.cpp
repro.cpp:18: warning: "INCLUDE_LEVEL" redefined
18 | # define INCLUDE_LEVEL 1
|
repro.cpp:2: note: this is the location of the previous definition
2 | # define INCLUDE_LEVEL 0
I'm not sure whether clang or g++'s behavior is more correct.
Compiler details:
$ circle --version ; echo ; clang --version ; echo ; g++ --version
circle version 1.0.0-135
Circle public preview build 135
Built Sep 26 2021 22:32:16
(c) 2021 Sean Baxter
https://www.circle-lang.org/
Twitter: @seanbax
clang version 10.0.0-4ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
The program
#include <iostream>
int main()
{
#if __CUDACC__
std::cout << "__CUDACC__ defined" << std::endl;
#endif
return 0;
}
Causes circle to emit the following error message:
$ circle --cuda-path=/usr/local/cuda -sm_50 repro.cu
preprocessor: repro.cu:5:5
expected value in conditional
Compiler details:
$ circle --version
circle version 1.0.0-136
Circle public preview build 136
Built Sep 27 2021 23:42:52
(c) 2021 Sean Baxter
https://www.circle-lang.org/
Twitter: @seanbax
cling based C++ as scripting language / hot code reload
Why? Able to run C++ script in runtime or compile it for max speed ( as in example https://github.com/derofim/cling-cmake )
HOT code reload
possible approaches:store app state
fix cling undo for files
https://root-forum.cern.ch/t/loading-unloading-class-as-interpreted-macro-in-cling-multiple-times/32976/2execute cling code to change callbacks & variables
nested cling::Interpreter with multiple cling::MetaProcessor
IDK how to do it, but you can create child cling::Interpreter
nvcc recognizes cu
as an option for the -x
command line language flag to indicate that the source file should be treated as CUDA code. It would be helpful if circle recognized this option as well to aid in porting old code bases.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.