Error: expression has no address - nim-lang

# lines 11-12:
proc last[T](ll: seq[T]): var T =
return ll[high(ll)]
# line 118:
if last(formula)["state"] == c_empty:
Errors:
main.nim(118, 12) Info: template/generic instantiation from here
main.nim(12, 12) Error: expression has no address
What the compiler wants?

[] does not return a var.
I don't think you need to annotate anything in this snippet with var though, since nothing is being mutated. Specify var at the call site if needed.
Try to submit compilable examples in the future if you can.

Related

How to catch the output of a compiler error in nim?

I am not sure if this is currently possible (and maybe it is not even advisable), but I would like to be able to catch the output of a compiler error and reuse it in code. An example would be:
type IntOrString = int | string
var s: seq[IntOrString]
this code would not compile with error:
/usercode/in.nim(2, 5) Error: invalid type: 'IntOrString' in this context: 'seq[IntOrString]' for var
I am interested in a way to be able to use the message of this error in the code.
My use case is being able to easily document and discuss compiler errors in nimib. If I were to write a document that shows and discuss the different type of compiler errors catching the message automatically that could be useful (a workaround right now would be to write the code to file and compile with verbosity 0).
It is possible to use the compiler api to catch errors:
import ../compiler/[nimeval, llstream, ast, lineinfos, options], os, strformat
let std = findNimStdLibCompileTime()
let modules = [std, std / "pure", std / "std", std / "core"]
var intr = createInterpreter("script", modules)
intr.registerErrorHook proc(config:ConfigRef,info:TLineInfo,msg:string,severity:Severity) =
raise newException(CatchableError,&"{severity}: {(info.line,info.col)} {msg}")
)
try:
intr.evalScript(llStreamOpen("""type IntOrString = int | string
var s: seq[IntOrString]"""))
except CatchableError as e:
echo e.msg
echo "done"
destroyInterpreter(intr)
outputs:
Error: (2, 4) invalid type: 'IntOrString' in this context: 'seq[IntOrS
tring]' for var
done
Caveat: you can't run runtime code at compile time, for example, trying to run
type Dog = object of RootObj
method speak(i:Dog):string = "woof"
echo Dog().speak()
in the interpreter will give you errors, instead you would have to do something like:
type Dog = object of RootObj
method speak*(i:Dog):string = "woof"
proc newDog*():Dog = discard
let
dog = intr.callRoutine(intr.selectRoutine("newDog"),[])
speech = intr.callRoutine(intr.selectRoutine("speak"),[dog])
if speech.kind == nkStrLit:
echo speech.strval

Checking the size of a user defined string litteral at compile time in C++11

I'm trying to restrict the use of some user defined litteral for string to a given length
Carte operator"" _C (const char* str, std::size_t sz) {
if (sz != 2)
throw runtime_error("Wrong size of string");
return from_string(str);
}
This works perfectly except that since litteral is known at compile time, the size test could be done at that time as well. However the I can't use a static assert here
jeu.cpp:105:17: error: static_assert expression is not an integral constant expression
static_assert(sz == 2, "Wrong size of string");
^~~~~~~
jeu.cpp:105:17: note: read of non-const variable 'sz' is not allowed in a constant expression
jeu.cpp:104:51: note: declared here
Is there a way to check the size of user defined string litteral at compile time in c++11 ?
If not, is it possible with more recent standard of c++ ?
use sizeof(test) to get length.. then you can use static_assert
const char test[] = "blablalba";
static_assert (sizeof(test) == 10);

Groovy - Type checking in script not working as expected

I have a Groovy application in which I allow the user to add custom behavior via Groovy scripts. I include those scripts via GroovyShell and type check them via Type Checking Extensions. The full code of how I include the script in my application is:
def config = new CompilerConfiguration()
config.addCompilationCustomizers(
new ASTTransformationCustomizer(TypeChecked)
)
def shell = new GroovyShell(config)
shell.evaluate(new File("path/to/some/file.groovy"))
This works fine. However, type checking in the script seems to be seriously broken. For example, I can include the following scripts without any complaint from the compiler:
String test = getTestValue() // automatic conversion from Integer to String. But WHY?
println "The value is $test" // shows as "The value is 0" on the console
private Integer getTestValue(){
return 0
}
I can even go further than that. When creating a class inside the script, I can assign it to a String without any error:
String y = new Test()
println y // shows Test#somenr on the console
class Test { }
Other type checks do work. I have not discovered any logic behind it yet, so any pointers in the right direction are greatly appreciated.
If in doubt, disasm. This is the bit around a call similar to yours: String x = new T():
0: invokestatic #17 // Method $getCallSiteArray:()[Lorg/codehaus/groovy/runtime/callsite/CallSite;
3: astore_1
4: aload_1
5: ldc #40 // int 1
7: aaload
8: ldc #42 // class T
10: invokeinterface #46, 2 // InterfaceMethod org/codehaus/groovy/runtime/callsite/CallSite.callConstructor:(Ljava/lang/Object;)Ljava/lang/Object;
15: invokestatic #52 // Method org/codehaus/groovy/runtime/typehandling/ShortTypeHandling.castToString:(Ljava/lang/Object;)Ljava/lang/String;
18: checkcast #54 // class java/lang/String
So this is the culprit for that cast. This seems also to hold true for #TypeChecked/#CompileStatic.
This is most likely a bug in the Static Type Checker. When LHS of the expression is a String variable, a conversion invoking ShortTypeHandling.castToString() is applied to the RHS.
This holds true as of Groovy 2.4.13.

Inline C Varnish (VCL_deliver)

I am using Varnish 4.0.
My backend is adding to some responses an http header "x-count"
I would like to log the value of "x-count" into a file with a line break.
I assumed i should do it in VCL deliver.
Here is what i have so far :
sub vcl_deliver {
if (resp.http.x-count-this:) {
set resp.http.X-infodbg = "xx";
C{
FILE *fp;
fp = fopen("/tmp/test.txt", "w+");
fputs(VRT_GetHdr(sp, HDR_OBJ, "\013x-count-this:"), fp);
fputs("\n", fp);
fclose(fp);
}C
}
}
Of course it doesnt work and there is a couple of errors ..
./vcl.gK2lu7uM.c: In function ‘VGC_function_vcl_deliver’:
./vcl.gK2lu7uM.c:1049:22: error: ‘sp’ undeclared (first use in this
function) ./vcl.gK2lu7uM.c:1049:22: note: each undeclared identifier
is reported only once for each function it appears in
./vcl.gK2lu7uM.c:1049:5: error: passing argument 2 of ‘VRT_GetHdr’
makes pointer from integer without a cast [-Werror]
./vcl.gK2lu7uM.c:330:7: note: expected ‘const struct gethdr_s *’ but
argument is of type ‘int’ ./vcl.gK2lu7uM.c:1049:5: error: too many
arguments to function ‘VRT_GetHdr’ ./vcl.gK2lu7uM.c:330:7: note:
declared here
I have to say that i simply copy/pasted "sp" from some examples, but i have no idea where it comes from (i suppose the inline C was in a different context and therefore it was declared there but not in vcl_deliver)
So the probably undocumented differences between Varnish 4 and 3 in the above examples are :
VRT_GetHdr is now VRT_GetHdr(context, struct gethdr_s)
sp doesn't exist, but there is a "ctx" variable
Found this, there :
http://jan.bogutzki.de/Artikel/395/set-ttl-in-varnish-4.html
char *stuffid;
const struct gethdr_s hdr = { HDR_BERESP, "\015x-count-this:" };
stuffid = VRT_GetHdr(ctx, &hdr);
And now a different story: Varnish is crashing as soon as the backend sends back "count-this", but that is a different problem :p (my crappy C code probably)
I don't have Varnish 4.0 handy to test this out, but I was able to get your example working with Varnish 3.0. When I tried the VCL as is, I wasn't getting the exact error you are though. The first change:
if (resp.http.x-count-this:) {
needs to be:
if (resp.http.x-count-this) {
The colon should be left off of the header name when referred to this way. Next:
fputs(VRT_GetHdr(sp, HDR_OBJ, "\013x-count-this:"), fp);
needs to be:
fputs(VRT_GetHdr(sp, HDR_OBJ, "\015x-count-this:"), fp);
The length value in that string needs to be in octal for some reason, and 13 in octal is 15. Making those changes got this to work for me. That being said, you many want to look into using open and fcntl instead of fopen since without file locking I'm not sure what the effect of multiple requests contending for that file would be.

Haskell FFI stack size with a C++ shared library

I am trying to send a very large amount of data, on the order of several Gigabytes to Haskell via a shared library. Everything seems to work fine up to a point, but I eventually get the error:
Stack space overflow: current size 8388608 bytes.
Use `+RTS -Ksize' to increase it.
So basically, my question is: How do I increase the Haskell stack size?
I have tried:
1) Passing the appropriate -rtsopts flags to the linker when building the shared library -- No luck, but this is expected because I am using the Haskell as a shared library.
2) Calling hs_init with the RTS flags as described in this link:
Haskell User Guide FFI/GHC...which did not work either.
int argc = 2;
char *argv[] = { "+RTS", "-K100M", NULL };
char **pargv = argv;
// Initialize Haskell runtime
hs_init(&argc, &pargv);
Basically I think that these arguments are also ignored because I am not using a Haskell main, which is also described in the user guide link I provided.
NOTE: I have also tried this approach adding a "-RTS" to the list before NULL and increasing argc but it made no difference.
3) I suspect that the true solution to this problem would be by following section 8.2.1.1 in the given link and making the special call to hs_init_ghc as so:
#include "HsFFI.h"
#include "Rts.h"
RtsConfig conf = defaultRtsConfig;
conf.rts_opts_enabled = RtsOptsAll;
hs_init_ghc(&argc, &argv, conf);
However when I try to do this as described in the guide, my C code that calls:
hs_init_ghc
will NOT compile due to a whole bunch of errors which I have pasted into the bottom of this question. It seems that including RTS.h will not compile, but I am following the example exactly, and compiling with:
ghc -c foo.cpp
I am wondering if anyone has any advice on how to get around this compilation error or to set the stack-size to a bigger value when using the Haskell as a shared library from C++?
I have also tried setting the corresponding environment variable, which also did not work. I even got a message saying it will be ignored.
I am using GHC version 7.4.1
Thanks very much for your help.
--JL
Compilation errors are:
>
In file included from /usr/lib/ghc/include/Rts.h:222:0:
0, from foo.cpp:6:
/usr/lib/ghc/include/rts/storage/Block.h:227:26:
error: expected ‘,’ or ‘...’ before ‘new’
dbl_link_replace(bdescr *new, bdescr *old, bdescr **list)
^
/usr/lib/ghc/include/rts/storage/Block.h: In function ‘void dbl_link_replace(bdescr*)’:
/usr/lib/ghc/include/rts/storage/Block.h:229:8:
error: expected type-specifier before ‘->’ token
new->link = old->link;
^
/usr/lib/ghc/include/rts/storage/Block.h:229:8:
error: expected ‘;’ before ‘->’ token
/usr/lib/ghc/include/rts/storage/Block.h:230:8:
error: expected type-specifier before ‘->’ token
new->u.back = old->u.back;
^
/usr/lib/ghc/include/rts/storage/Block.h:230:8:
error: expected ‘;’ before ‘->’ token
/usr/lib/ghc/include/rts/storage/Block.h:231:9:
error: ‘old’ was not declared in this scope
if (old->link) {
^
/usr/lib/ghc/include/rts/storage/Block.h:232:32:
error: expected type-specifier before ‘;’ token
old->link->u.back = new;
^
/usr/lib/ghc/include/rts/storage/Block.h:234:9:
error: ‘old’ was not declared in this scope
if (old->u.back) {
^
/usr/lib/ghc/include/rts/storage/Block.h:235:32:
error: expected type-specifier before ‘;’ token
old->u.back->link = new;
^
/usr/lib/ghc/include/rts/storage/Block.h:237:10:
error: ‘list’ was not declared in this scope
*list = new;
^
/usr/lib/ghc/include/rts/storage/Block.h:237:20:
error: expected type-specifier before ‘;’ token
*list = new;
^
In file included from /usr/lib/ghc/include/Rts.h:218:0:
0,
from foo.cpp:6:
/usr/lib/ghc/include/rts/storage/ClosureMacros.h: In function ‘rtsBool
More compile errors removed...but available upon request.

Resources