I trying to compile a code and it gives me a non-sense error, I'm very new to oCaml so I'm missing something for sure
Here is the code
let foo () =
if '\n' = '\n' then begin
print_endline "foo";
end
Here is the error when I run dune build
File "gkoeditor.ml", line 46, characters 7-11:
46 | if '\n' = '\n' then begin
^^^^
Error: This expression has type char but an expression was expected of type
int
The whole source code can be found here https://github.com/dhilst/gkoeditor
I'm using Curses and Core libraries, for sure something is messing up with my environment,
Regards
I believe that Core overrides the definition of = so that it is of type int -> int -> bool. The justification is that the polymorphic comparison sometimes causes problems. (It can cause an exception if the types contain functions, and can diverge in the presence of cyclic structures.)
Polymorphic = has never caused me any problems, and I find this redefinition to be a bit troubling for exactly the reason that it generates errors that seem to make no sense. However I can see the advantages.
At any rate, you can fix this by asking specifically for the polymorphic version of = in the Poly module.
Related
For my Masters degree I need to work on a database called duckdb (its on git hub). Normally on Linux you can simply clone it and "make" it to install.
I tired the same on windows after installing CMake and Cygwin.
But halfway through compiling I get the error
'DUCKDB~2/duckdb/THIRD_~1/catch/catch.hpp:1445:96:
error: ISO C++
forbids comparison between pointer and integer [-fpermissive]
auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); }'
Since I doubt that the creators of duckdb did mess this up, I think there is a compiler error trying to compile a C file as C++ file, maybe.
My main problem is: how do I configure the make command on windows to stop it from producing this error?
I tried it both on a windows 7 and 10 system with gcc 5.1 and current cmake installed, and both produce this error.
Edit: Here is the full error text
[ 87%] Building CXX object test/sql/capi/CMakeFiles/test_sql_capi.dir/ub_test_sql_capi.cpp.obj
In file included from C:/duckdb/test/sql/capi/test_capi.cpp:1:0,
from test_capi.cpp:0:
C:/DUCKDB~2/duckdb/THIRD_~1/catch/catch.hpp: In instantiation of 'bool >Catch::compareNotEqual(const LhsT&, RhsT&&) [with LhsT = void*; RhsT = const >long long int&]':
C:/DB/DUCKDB~2/duckdb/THIRD_~1/catch/catch.hpp:1471:37: required from 'const >Catch::BinaryExpr Catch::ExprLhs::operator!=(const >RhsT&) [with RhsT = long long int; LhsT = void* const&]'
C:/DB/duckdb/test/sql/capi/test_capi.cpp:332:2: required from here
C:/DB/DUCKDB~2/duckdb/THIRD_~1/catch/catch.hpp:1445:96: error: ISO C++ forbids comparison >between pointer and integer [-fpermissive]
auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return >static_cast(lhs != rhs); }
I only edited out my user name in the path etc.
I don't know the library, so I can't give definite answer. I will be going by the code at https://github.com/cwida/duckdb.
According to the error message in the problematic code is in line 332 of test/sql/capi/test_capi.cpp, which is:
REQUIRE(stmt != NULL);
REQUIRE is a macro from the unit testing library Catch2 that does some magic to parse the expression given to it. The important part is that stmt != NULL will not actually be executed immediately, but only through function indirection.
stmt is declared as in line 324 as
duckdb_prepared_statement stmt = nullptr;
and duckdb_prepared_statement is a typedef in line 94 of src/include/duckdb.h:
typedef void *duckdb_prepared_statement;
Therefore the intention of the problematic line is to check whether stmt is still a nullptr after some intermediate operations.
Normally stmt != NULL would be fine for that. However because the Catch2 macro introduces intermediate function calls rather than evaluating this expression directly, implicit conversions that are specific to the literal are not applied.
In particular NULL is according to the standard either a prvalue of type std::nullptr_t or an integer literal with value 0. Which of these exactly (and which integer type) is implementation-defined.
Comparing integers and pointers is generally forbidden, however integer literals of value zero have a special exception allowing them to be implicitly converted to a null pointer of any pointer type. This is what would happen if stmt != NULL would be evaluated directly.
However due to the interjection of Catch2, NULL is first passed around and later compared through a variable to stmt, which makes the special zero literal rule not apply any more. Therefore a comparison of stmt against NULL through REQUIRE would fail if NULL is an integer literal in the current implementation.
Catch2 does consider this problem and there are overloads for compareNotEqual in third_party/catch/catch.hpp that take care of the case where NULL is a zero integer literal of type int or long, but for some reason the case of long long is not considered. I don't know whether this is a problem with Catch2 or whether it is only in the cloned version included in duckdb.
So, if the implementation uses a zero literal of type long long for NULL, then the error you observed will happen.
Really duckdb should use nullptr instead of NULL (as it does in the initialization), which does not have these problems and was added to the language because of exactly these problems.
I suppose you can simply try to fix this issue by replacing NULL with nullptr (maybe in other test cases as well).
However the problematic code is only in files which are themselves unit tests for the actual library code. So there should be some option to cmake or make that will disable building the unit tests, so that you can ignore this particular error, hoping that it doesn't occur anywhere in the actual library code as well.
If I was correct in my assessment, you might want consider filing a bug report for this with duckdb, assuming they do support your platform in the first place.
Rather than using Cygwin, it might be easier to use CMake combined with Visual Studio to compile the project. This is the way that the authors compile and test DuckDB on Windows themselves.
Using CMake, generate a set of Visual Studio Project files. Then open those project files in Visual Studio (we use Visual Studio Community 2019), and compile and run the test suite (unittest). Individual tests can be run by adding the test name as a command line parameter.
DuckDB doesn't seem to have a release version at this time. So don't assume it the creators didn't leave any errors in...
You can add compiler flag -fpermissive to ignore the error (e.g. make CXX="g++ -fpermissive").
But ignoring errors like this isn't always safe.
So I tried to fix the issue, and I was able to build a version on Windows. See https://github.com/cwida/duckdb/issues/361 for my solution.
Coderbyte is an online coding challenge site (I found it just 2 minutes ago).
The first C++ challenge you are greeted with has a C++ skeleton you need to modify:
#include <iostream>
#include <string>
using namespace std;
int FirstFactorial(int num) {
// Code goes here
return num;
}
int main() {
// Keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
If you are little familiar with C++ the first thing* that pops in your eyes is:
int FirstFactorial(int num);
cout << FirstFactorial(gets(stdin));
So, ok, the code calls gets which is deprecated since C++11 and removed since C++14 which is bad in itself.
But then I realize: gets is of type char*(char*). So it shouldn't accept a FILE* parameter and the result shouldn't be usable in the place of an int parameter, but ... not only it compiles without any warnings or errors, but it runs and actually passes the correct input value to FirstFactorial.
Outside of this particular site, the code doesn't compile (as expected), so what is going on here?
*Actually the first one is using namespace std but that is irrelevant to my issue here.
I'm the founder of Coderbyte and also the guy who created this gets(stdin) hack.
The comments on this post are correct that it is a form of find-and-replace, so let me explain why I did this really quickly.
Back in the day when I first created the site (around 2012), it only supported JavaScript. There was no way to "read in input" in JavaScript running in the browser, and so there would be a function foo(input) and I used the readline() function from Node.js to call it like foo(readline()). Except I was a kid and didn't know better, so I literally just replaced readline() with the input at run-time. So foo(readline()) became foo(2) or foo("hello") which worked fine for JavaScript.
Around 2013/2014 I added more languages and used third-party service to evaluate code online, but it was very difficult to do stdin/stdout with the services I was using, so I stuck with the same silly find-and-replace for languages like Python, Ruby, and eventually C++, C#, etc.
Fast forward to today, I run the code in my own containers, but never updated the way stdin/stdout works because people have gotten used to the weird hack (some people have even posted in forums explaining how to get around it).
I know it is not best practice and it isn't helpful for someone learning a new language to see hacks like this, but the idea was for new programmers to not worry about reading input at all and just focus on writing the algorithm to solve the problem. One common complaint about coding challenge sites years ago was that new programmers would spend a lot of time just figuring out how to read from stdin or read lines from a file, so I wanted new coders to avoid this problem on Coderbyte.
I'll be updating the entire editor page soon along with the default code and stdin reading for languages. Hopefully then C++ programmers will enjoy using Coderbyte more :)
I am intrigued. So, time to put the investigation goggles on and since I don't have access to the compiler or compilation flags I need to get inventive. Also because nothing about this code makes sense it's not a bad idea question every assumption.
First let's check the actual type of gets. I have a little trick for that:
template <class> struct Name;
int main() {
Name<decltype(gets)> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
And that looks ... normal:
/tmp/613814454/Main.cpp:16:19: warning: 'gets' is deprecated [-Wdeprecated-declarations]
Name<decltype(gets)> n;
^
/usr/include/stdio.h:638:37: note: 'gets' has been explicitly marked deprecated here
extern char *gets (char *__s) __wur __attribute_deprecated__;
^
/usr/include/x86_64-linux-gnu/sys/cdefs.h:254:51: note: expanded from macro '__attribute_deprecated__'
# define __attribute_deprecated__ __attribute__ ((__deprecated__))
^
/tmp/613814454/Main.cpp:16:26: error: implicit instantiation of undefined template 'Name<char *(char *)>'
Name<decltype(gets)> n;
^
/tmp/613814454/Main.cpp:12:25: note: template is declared here
template <class> struct Name;
^
1 warning and 1 error generated.
gets is marked as deprecated and has the signature char *(char *). But then how is FirstFactorial(gets(stdin)); compiling?
Let's try something else:
int main() {
Name<decltype(gets(stdin))> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
Which gives us:
/tmp/286775780/Main.cpp:15:21: error: implicit instantiation of undefined template 'Name<int>'
Name<decltype(8)> n;
^
Finally we are getting something: decltype(8). So the entire gets(stdin) was textually replaced with the input (8).
And the things get weirder. The compiler error continues:
/tmp/596773533/Main.cpp:18:26: error: no matching function for call to 'gets'
cout << FirstFactorial(gets(stdin));
^~~~
/usr/include/stdio.h:638:14: note: candidate function not viable: no known conversion from 'struct _IO_FILE *' to 'char *' for 1st argument
extern char *gets (char *__s) __wur __attribute_deprecated__;
So now we get the expected error for cout << FirstFactorial(gets(stdin));
I checked for a macro and since #undef gets seems to do nothing it looks like it isn't a macro.
But
std::integral_constant<int, gets(stdin)> n;
It compiles.
But
std::integral_constant<int, gets(stdin)> n; // OK
std::integral_constant<int, gets(stdin)> n2; // ERROR wtf??
Doesn't with the expected error at the n2 line.
And again, almost any modification to main makes the line cout << FirstFactorial(gets(stdin)); spit out the expected error.
Moreover the stdin actually seems to be empty.
So I can only conclude and speculate they have a little program that parses the source and tries (poorly) to replace gets(stdin) with the test case input value before actually feeding it into the compiler. If anybody has a better theory or actually knows what they are doing please share!
This is obviously a very bad practice. While researching this I found there is at least a question here (example) about this and because people have no idea that there is a site out there who does this their answer is "don't use gets use ... instead" which is indeed a good advice but only confuses the OP more since any attempt at a valid read from stdin will fail on this site.
TLDR
gets(stdin) is invalid C++. It's a gimmick this particular site uses (for what reasons I cannot figure out). If you want to continue to submit on the site (I am neither endorsing it neither not endorsing it) you have to use this construct that otherwise would not make sense, but be aware that it is brittle. Almost any modifications to main will spit out an error. Outside of this site use normal input reading methods.
I tried the following addition to main in the Coderbyte editor:
std::cout << "gets(stdin)";
Where the mysterious and enigmatic snippet gets(stdin) appears inside a string literal. This shouldn't possibly be transformed by anything, not even the preprocessor, and any C++ programmer should expect this code to print the exact string gets(stdin) to the standard output. And yet we see the following output, when compiled and run on coderbyte:
8
Where the value 8 is taken straight from the convenient 'input' field under the editor.
From this, it's clear that this online editor is performing blind find-and-replace operations on the source code, substitution appearances of gets(stdin) with the user's 'input'. I would personally call this a misuse of the language that's worse than careless preprocessor macros.
In the context of an online coding challenge website, I'm worried by this because it teaches unconventional, non-standard, meaningless, and at least unsafe practices like gets(stdin), and in a manner that can't be repeated on other platforms.
I'm sure it can't be this hard to just use std::cin and just stream input to a program.
I have a file that contains an arbitrary number of lines of c++ code, each line of which is self-contained (meaning it is valid by itself in the main function). However, I do not know how many, if any, of the lines will have valid c++ syntax. An example file might be
int length, width; // This one is fine
template <class T className {}; // Throws a syntax error
What I want to do is write to a second file all the lines that have valid syntax. Currently, I've written a program in python that reads each line, places it into the following form
int main() {
// Line goes here
return 0;
}
and attempts to compile it, returning True if the compilation succeeds and False if it doesn't, which I then use to determine which lines to write to the output file. For example, the first line would generate a file containing
int main() {
int length, width;
return 0;
}
which would compile fine and return True to the python program. However, I'm curious if there is any sort of try-catch syntax that works with the compiler so I could put each line of the file in a try-catch block and write it to the output if no exception is thrown, or if there's a way I can tell the compiler to ignore syntax errors.
Edit: I've been asked for details about why I would need to do this, and I'll be the first to admit it's a strange question. The reason I'm doing this is because I have another program (of which I don't know all the implementation details) that writes a large number of lines to a file, each of which should be able to stand alone. I also know that this program will almost certainly write lines that have syntax errors. What I'm trying to do is write a program that will remove any invalid lines so that the resulting file can compile without error. What I have in my python program right now works, but I'm trying to figure out if there is a simpler way to do it.
Edit 2: Though I think I've got my answer - that I can't really play try-catch with the compiler, and that's good enough. Thanks everyone!
Individual lines of code that are syntactically correct in the context of a C++ source file are not necessarily syntactically correct by themselves.
For example this:
int length, width;
happens to be valid either as part of a main function or by itself -- but it has a different meaning (by itself it defines length and width as static objects).
This:
}
is valid in context, but not by itself.
There is typically no way for a compiler to ignore syntax errors. Once a syntax error has been encountered, the compiler has no way to interpret the rest of the code.
When you're reading English text, adfasff iyufoyur; ^^$(( -- but you can usually recover and recognize valid syntax after an error. Compilers for programming languages aren't designed to perform that kind of recovery; probably the nature of C++'s syntax would make it more difficult, and there's just not enough demand to make it worth doing.
I'm not sure what your criterion for a single line of code being "correct" is. One possibility might be to write the line of code to a file, contained in a definition of main:
int main() {
// insert arbitrary line here
}
and then compile the resulting source file. I'm not sure that I can see how that would be particularly useful, but it's about the closest I can come to what you're asking for.
What do you mean by "each line is self-contained"? If the syntax of a line of C++ code is valid may depend largely on the code before or after that line. A given line of code might be valid within a function, but not outside a function body. So, as long as you can't define what you mean by "self-contained" it is hard to solve your problem.
I'm working with a C++ code base with a very peculiar coding style, including prefixing member variables in classes with '$'. For anyone who's never come across this before, it's not formally part of C++ standards, but lurks around for backwards compatibility.
As an example of what I'm talking about:
#include <iostream>
class T { public: int $x; int y; };
int main()
{
T *t = new T();
t->$x = t->y = 42;
std::cout << "t->$x = " << t->$x << std::endl;
delete t;
return 0;
}
This introduces a problem in GDB. GDB normally uses $ prefixed variables as a magic convenience variable (such as referring to previous values). Fire up GDB, set a breakpoint at the cout statement, and try to print t->$x.
p t runs fine. p *t runs fine. p t->y runs fine. p t->$x returns a syntax error, presumably expecting the $ to refer to a convenience variable.
Ideally, I'd strip the $s out entirely and spend the rest of my days hunting down whoever thought that was a good idea (especially for a modern codebase). That's not realistic, but I still need to be able to use GDB for debugging.
I'm hoping there's a magic escape character, but nothing I've searched for or tried has worked.
Examples:
p this->'\044descriptor'
p this->'$descriptor'
p this->'$'descriptor
p this->\$descriptor
p this->\\$descriptor
p this->'\$descriptor'
p this->'\\044descriptor'
p this->$$descriptor
p this->'$$descriptor'
and so on.
In this particular case, I can run the getter function (p this->getDescriptor()). An uglier workaround is to print the entire class contents (p *this). I'm not sure I can rely on both of those indefinitely; some of the classes are fairly large, and most member variables don't have getters.
This could potentially be classified as a bug in GDB, depending on whether it's a good idea to rip up input to support this. However, even if it was fixed, I'm stuck on GDB 7.2 for the given architecture/build environment.
Any ideas?
UPDATE: python import gdb; print (gdb.parse_and_eval("t")['$x']) as suggested in the comment works if you have python builtin (which I don't have, unfortunately).
If you got the gdb version with python extensions, maybe the "explore" feature will help.
See https://sourceware.org/gdb/onlinedocs/gdb/Data.html#Data
(gdb) explore cs
The value of `cs' is a struct/class of type `struct ComplexStruct' with
the following fields:
ss_p =
arr =
Enter the field number of choice:
Since you don't need the variable name, you should be able to step around the '$' issue.
I'm currently trying to compile a python project (5files # total 1200 lines of code) with shedskin.
I tried shedskin Version 0.9.3 and 0.9.2 both result in the same errors.
This is the first error I encounter:
mmain.cpp: In function ‘__shedskin__::list<__shedskin__::list<int>*>* __mmain__::list_comp_3(__shedskin__::__ss_int)’:
mmain.cpp:133: error: no matching function for call to ‘__shedskin__::list<__shedskin__::list<int>*>::append(__shedskin__::list<double>*)’
Moreover, I after running shedskin (i.e. before typing "make") I receive many warnings - all related to dynamic types:
*WARNING* mmain.py: expression has dynamic (sub)type: {float, int, list}
However, shedskin seems to work flawlessly with the provided examples since I can compile and execute them without any errors.
Do you have an idea where to look for the error or what the error is related to?
mmain.cpp:133: error: no matching function for call to ‘__shedskin__::list<__shedskin__::list<int>*>::append(__shedskin__::list<double>*)’
This error means that you've got a Python object that shedskin has inferred as a list of lists of ints, but now you're trying to append something that it's inferred as a list of floats. You can get that by, for example, doing this:
a = [[1], [2]]
b = 1.0
a.append([b])
However, from the line above it, the function name is list_comp_3. Unless you've actually named a function list_comp_3 (which you haven't), this is a list comprehension. So, you may be doing something like this:
a = [1, 2, 3.0]
b = [[i] for i in a]
You may be wondering why it let you get away with a but failed on b. Well, first of all, it probably didn't really let you get away with it, if you've got dozens of warnings you haven't dealt with. But second, as the documentation says:
Integers and floats can often be mixed, but it is better to avoid this where possible, as it may confuse Shed Skin:
a = [1.0]
a = 1 # wrong - use a float here, too
As for the warnings, they can mean anything from "you got away with it this time, but don't expect to always do so" to "an error is coming up related to this" to "this will compile, but to something less efficient than the original Python code rather than more" to "this will compile, but to something incorrect".
More generally, it sounds like your program just can't be statically typed by shedskin's inference engine. Without actually seeing your code, it's impossible to tell you what you're doing wrong, but if you re-read the Typing Restrictions and Python Subset Restrictions sections of the docs, that should give you ideas of what kinds of things are and aren't appropriate.
to avoid confusion, please note that both code snippets provided by 'abartert' compile and run fine when compiled separately (shedskin 0.9.3). my guess is also that the problem should disappear after resolving the dynamic typing warnings. if not, I'd be very interested in seeing the program you are trying to compile, or at least enough of it to reproduce the problem.
update: btw, as of 0.9.1 or so, shedskin should be smarter about int and float mixing. if it encounters something that would lead to broken or inefficient c++ code (because of necessary run-time conversion of sorts), it should now usually complain with an 'incompatible types' warning. so perhaps it's time to update this part of the documentation slightly for 0.9.3.