<Drakken>
What does it mean when camlp4 doesn't tell you what kind of syntax error it found?
<thelema>
Drakken: campl4 is bad?
tufisi has quit [Ping timeout: 252 seconds]
<Drakken>
Ha! The built-in parser thought I was repeatedly redefining the function "value" :)
<Drakken>
or something else...
<thelema>
:)
<_habnabit>
there's something very satisfying about having written an ocaml implementation of an algorithm and comparing it against a C++ implementation of the same algorithm, only to find that the ocaml implementation is gobs faster
<thelema>
_habnabit: yes, that is very satisfying. same data structures?
<_habnabit>
nope! AFAICT the C++ is pretty poorly done. lots of STL vectors. mine uses GSL matrix multiplication
<Drakken>
Why would the built-in compiler accept code that looks like [foo <args> = <expr>; foo <other args> = <other expr>; etc.]?
<Drakken>
mrvn syntax. fun [ Some x -> | None -> ... ]
<Drakken>
camlp4o chokes on "fun" in the expr parser, but ocamlc just complains about the arrow with no explanation.
<Drakken>
oops. I mean Some x -> x
<mrvn>
# fun Some x -> | None -> ();;
<mrvn>
Error: Syntax error
<mrvn>
with an _ on |
<mrvn>
What more do you want?
<Drakken>
see above
<Drakken>
fun [ Some x -> x | None -> ... ]
<Drakken>
so it's really just the syntax of the fun expression, but camlp4o tells you that's what it is and points to the beginning of the expression.
<mrvn>
Drakken: and ocamlc/opt points at the point where you forgot the expression
<Drakken>
mrvn points to the first arrow
<Drakken>
I mean ocamlc points to the arrow. I assume mrvn has better things to do :/
<mrvn>
Drakken: because an arrow inside a list isn't allowed
<mrvn>
Drakken: fun [ Some x ] -> ... would be ok.
<pippijn>
and [ fun Some x -> ... ], too
<pippijn>
ah no
<pippijn>
missing ()
<mrvn>
pippijn: () are overrated :)
<pippijn>
I think it'll work with function, thought
<pippijn>
-t
<mrvn>
# [ fun Some x -> x ];;
<mrvn>
Error: The constructor Some expects 1 argument(s), but is applied here to 0 argument(s)
<mrvn>
pippijn: you are right
<mrvn>
# [ fun (Some x) -> x ];; - : ('a option -> 'a) list = [<fun>]
<pippijn>
while you're having fun with the repl, have you done this: type t = A of t;; let rec a = A b and b = A a;;
<thelema>
pippijn: ah, yes. I recall this now. Although I'm thinking something more like generating a lossless parse tree that can be inspected by various rules to identify common mistakes
<pippijn>
thelema: ah
<pippijn>
yeah, I started doing this, but I grew tired of it
<thelema>
yes, it's definitely more work.
<mrvn>
pippijn: any recurisve data structure is fun in the toplevel
<thelema>
The other alternative is to hand-write a recursive descent parser for ocaml's grammar
<pippijn>
that's probably even more work
<thelema>
the trick would be making sure it's compatible with existing code, and yes, it'd be even more work
<thelema>
although ocaml's grammar isn't quite as bad as some languages
<pippijn>
but that way, you could do proper error recovery
<pippijn>
error recovery with menhir is not so much fun
<rgrig>
ross cox has a recent blog post about error messages with bison, based on some article. i'm upgrading ubuntu now so my browser is kinda unusable, which is why i don't give an url
<pippijn>
the default error message generated by my extension shows a list of tokens that could cause the current state to shift
<pippijn>
you can also supply your own for a state/token pair (or just a state)
<pippijn>
also, it will limit the tokens suggested if some can be found with a low levenshtein distance
<pippijn>
if you enter "__attribute((beak" in the parser example above, you'll see what I mean
<pippijn>
rgrig: that article is basically what I do, in addition to the token lists
<rgrig>
sorry, as i said i can't use browser now. what you were talking sounded very similar to that article so i thought you might want to know about it :)
<rgrig>
i have to go now. bye
rgrig has quit [Quit: Leaving]
everyonemines has joined #ocaml
iago has quit [Quit: Leaving]
johnnowak has joined #ocaml
johnnowak has left #ocaml []
gnuvince has quit [Ping timeout: 260 seconds]
mattrepl has quit [Quit: mattrepl]
hyperboreean has quit [Ping timeout: 252 seconds]
hyperboreean has joined #ocaml
sivoais has quit [Quit: Lost terminal]
sivoais has joined #ocaml
everyonemines has quit [Quit: Leaving.]
smerz has quit [Remote host closed the connection]
oriba_ has joined #ocaml
oriba has quit [Ping timeout: 252 seconds]
gnuvince has joined #ocaml
Transformer has joined #ocaml
Transformer has quit [Excess Flood]
oriba_ has quit [Quit: oriba_]
tufisi has joined #ocaml
ftrvxmtrx_ has quit [Ping timeout: 252 seconds]
ftrvxmtrx_ has joined #ocaml
ankit9 has joined #ocaml
ftrvxmtrx_ has quit [Quit: Leaving]
f[x] has joined #ocaml
thomasga has joined #ocaml
djcoin has joined #ocaml
ftrvxmtrx has joined #ocaml
cago has joined #ocaml
ttamttam has joined #ocaml
krktz has quit [Ping timeout: 240 seconds]
avsm has quit [Quit: Leaving.]
mononofu has joined #ocaml
krktz has joined #ocaml
mika2 has joined #ocaml
gildor_ has joined #ocaml
maufred_ has joined #ocaml
pippijn_ has joined #ocaml
pippijn has quit [Ping timeout: 248 seconds]
tomprince has quit [Ping timeout: 248 seconds]
gildor has quit [Ping timeout: 248 seconds]
maufred has quit [Ping timeout: 248 seconds]
snarkyboojum has quit [Ping timeout: 248 seconds]
snarkyboojum has joined #ocaml
tomprince has joined #ocaml
avsm has joined #ocaml
Submarine has joined #ocaml
Submarine has quit [Changing host]
Submarine has joined #ocaml
pheredhel has joined #ocaml
Derander_ has joined #ocaml
hyperbor1ean has joined #ocaml
fds has joined #ocaml
xaimus_ has joined #ocaml
dgfitch_ has joined #ocaml
hyperboreean has quit [*.net *.split]
fds_ has quit [*.net *.split]
pheredhel` has quit [*.net *.split]
dgfitch has quit [*.net *.split]
xaimus has quit [*.net *.split]
Derander has quit [*.net *.split]
noj has quit [*.net *.split]
noj has joined #ocaml
larhat has joined #ocaml
avsm has quit [Quit: Leaving.]
mononofu has quit [Remote host closed the connection]
roha has joined #ocaml
ocp has joined #ocaml
ankit9 has quit [Ping timeout: 250 seconds]
roha has quit [Ping timeout: 276 seconds]
joelr has joined #ocaml
Cyanure has joined #ocaml
Hussaind has joined #ocaml
jamii has joined #ocaml
Zwei has joined #ocaml
avsm has joined #ocaml
milosn has quit [Read error: Operation timed out]
ankit9 has joined #ocaml
thomasga has quit [Ping timeout: 260 seconds]
ankit9 has quit [Read error: Operation timed out]
ankit9 has joined #ocaml
err404 has joined #ocaml
<joelr>
moin
_andre has joined #ocaml
thomasga has joined #ocaml
hiptobecubic has joined #ocaml
Zwei has left #ocaml []
milosn has joined #ocaml
joelr has quit [Quit: joelr]
pippijn_ is now known as pippijn
ankit9 has quit [Ping timeout: 272 seconds]
tmaedaZ has joined #ocaml
tmaedaZ is now known as tmaeda
Submarine has quit [Quit: Leaving]
joelr has joined #ocaml
<joelr>
can you create ocaml objects from c?
Ptival has quit [Read error: Connection reset by peer]
Ptival has joined #ocaml
<joelr>
perhaps i should ask "how do you create ocaml objects from c"?
hiptobecubic has quit [Ping timeout: 245 seconds]
<adrien>
yes, although I can't remember how but iirc it's in the doc; however, you usually want to have the simplest interface with C to avoid bugs
<adrien>
making a low-level interface and then wrapping it in ocaml objects might be better
<adrien>
and C++ objects don't necessarily map best to OCaml objects
<rixed>
joelr: See 18.3.5 in the manual
<joelr>
adrien: i would love to know how you can wrap c++ objects in ocaml modules
<joelr>
rixed: checking
<rixed>
joelr: not intended to create object from C, though. Rather to read them.
<joelr>
rixed: i was just about to point that out
<mrvn>
joelr: just replied to the mail
<joelr>
in my case, i have a c++ "abstract class"
<joelr>
you are supposed to subclass it and implement the methods (callbacks) that you are interested in
<joelr>
some of those c++ methods get passed pointers to other objects
<mrvn>
joelr: do you ever need the derived class or just the basic interface?
<joelr>
so i need to create that "other object" on the c side somehow, before invoking the callback on the ocaml side
<joelr>
mrvn: can you elaborate?
<joelr>
mrvn: goswin?
<mrvn>
joelr: You can't have modules Base and Derived and have Derived.t inherit Base.t.
<joelr>
mrvn: why not?
<mrvn>
joelr: With C++ classes a Derived object gets atomatically cased to Base when you pass it to a function expecting a Base&. In Ocaml you get a type error.
<mrvn>
In ocaml you would have to call foo (Derived.as_base x)
<joelr>
mrvn: i was thinking of subclassing the c++ class on the c++ side and then providing a matching ocaml implementation with dummy methods
<joelr>
where all methods on the c++ side dispatch to ocaml
<joelr>
think of that as base
<joelr>
i would then subclass on the ocaml side
<joelr>
this is somewhat stupid since you are not supposed to have multiple instances of the callback class anyway
<joelr>
just one does it
<mrvn>
hmm, wait. What way do you want to call. The c++ Foo.bla() should call ocaml code?
<joelr>
correct
<joelr>
this is a trading api
<joelr>
say you register to be notified of incoming price quotes on a certain instrument (stock?)
<joelr>
you are supposed to implement a callback class and the "alert" method
<mrvn>
And ocaml provides the base class with all the callbacks and C++ the derives from that classes that call the callbacks?
<joelr>
then this method of your derived class is called whenever a price quote comes in
<joelr>
i want callbacks to be triggered on the ocaml side
<joelr>
so i subclass on the c++ side, implement all methods and have them call methods of the stored object pointer on the ocaml side
<joelr>
of course this assumes that i have instantiated the ocaml object, grabbed self and passed it to the new stub on the c side which stored self in the c++ object
<joelr>
mrvn: is this clear?
cago has quit [Ping timeout: 240 seconds]
<mrvn>
class Bar : public Foo { bar() { Foo::callback1(); } };
<mrvn>
joelr: caml_copy_string is for copying C strings, not byte arrays. so yes.
<joelr>
mrvn: thanks
<joelr>
am i correct that any ocaml values stored on the c side need to be declared as global gc roots?
<mrvn>
If your data is largish (>16k) then you might prefer bigarray.
<mrvn>
joelr: if it contains values then yes
<joelr>
fair
<mrvn>
joelr: global or local, but declared
<joelr>
mrvn: what's the value corresponding to no value?
<mrvn>
Val_unit?
<pippijn>
is it ok to return a C allocated object cast to value?
<joelr>
mrvn: e.g. if i want to have an array of closures where elements are not set initially
<joelr>
pippijn: i think you need to return it in a block
<mrvn>
pippijn: yes, pointers are passed unmodified and pointers to outside the ocaml heap are left alone
<joelr>
custom block
<pippijn>
mrvn: ok
<mrvn>
A custom block has the advantage that the GC tells you when ocaml no longer uses the value and you can free() it
<mrvn>
+ compare, hash, ...
<mrvn>
A custom block is usualy the better choice.
<pippijn>
I'm thinking about ncurses
<pippijn>
it returns pointers directly
<mrvn>
pippijn: do you need to free them?
<joelr>
if i pass a closure to the c side and want to call it later, do i just use callback(…), there's no need to declare it a callback on the ocaml side, right?
<mrvn>
Since we are on the topic of GC and C code. Can one allocate ocaml blocks so that the GC will not move them?
<mrvn>
joelr: there is no such thing as a callback. :)
<joelr>
mmm, right
<pippijn>
mrvn: no, I don't, I personally only use the stdscr
<mrvn>
joelr: you can pass a function value to the C side or have the C side look up a function name.
<joelr>
mrvn: i'm talking about callback.h
<pippijn>
I do viewports and stuff myself
<mrvn>
joelr: afaiks that "value closure" is just that, any closure. fun ...
<joelr>
ok
ftrvxmtrx has joined #ocaml
<joelr>
when do you need to call the CAMLparamN functions?
<mrvn>
joelr: when you have values as arguments and you might trigger an allocation (which includes releasing the runtime system)
<joelr>
fair
<joelr>
thanks
<mrvn>
if in doubt use it
<joelr>
often, the c++ compiler tells me these are unused
<mrvn>
I want a shallow option type. One that doesn't add an extra indirection. type 'a shallow option = NULL | 'a
<adrien>
how do you implement that? what about "(int shallow option) shallow option"
<mrvn>
Any smart hacks to implement this without having to capsulate that into a C call?
<pippijn>
mrvn: you could probably hack something with Obj.magic
err404 has quit [Remote host closed the connection]
<mrvn>
adrien: int != 0 would be ok and 'a shallow shallow would be ambigious with NULL
<mrvn>
adrien: it wouldn't be generally typesave.
<mrvn>
pippijn: let foo t = if Obj.magic t = 0 then None else Some (Obj.magic t)?
<pippijn>
= ()
<pippijn>
0 is actually 1, I think :)
<mrvn>
right, it probably compares against the tagged 0
<pippijn>
oh, no
<pippijn>
() is int 0
<mrvn>
() is tagged too
<pippijn>
yes
<mrvn>
So I need to declare a NULL somewhere and compare against that
<pippijn>
yes..
<mrvn>
still would require an "if". No pattern matching.
<mrvn>
and I don't know how to specify the type so the only 'a that are alowed are pointer that aren't shallow already.
<mrvn>
'a constrained 'a != int ...
<pippijn>
type enum = A | B | C
<pippijn>
is also int, basically
<mrvn>
yes
<mrvn>
[] too
<mrvn>
but 'a list option makes usualy no sense
<mrvn>
I guess one could add compiler support for '_a shallow that can't be used in a polymorphic contents and have the compiler give errors if the type is unsuitable.
<pippijn>
one could do a lot more if one got rid of the byte code backend :)
<mrvn>
My tiles have a mutable item : (Item.kind * int) option and mutable unit : Unit.t option. If I allocate tiles as C array then I can't use option types there.
<mrvn>
For the first I can use mutable item_num : int; mutable item_kind : Item.kind; with 0 indicating the item_kind is invalid. But the Unit.t option needs NULL | 'a.
<mrvn>
Or I need to allocate the Unit.t option following each tile and have a special C stub to set set it.
<mrvn>
Hmm, maybe I store units by index with 0 being reserved for unused.
<adrien>
33aa
<adrien>
blah
ftrvxmtrx_ has joined #ocaml
ftrvxmtrx has quit [Ping timeout: 276 seconds]
mononofu has joined #ocaml
csmrfx has joined #ocaml
<csmrfx>
good evening
<joelr>
what _val corresponds to a closure on the c side, e.g. if a variant constructor has a function argument?
<joelr>
woudln't it be just Field(v, 0) for the 1st argument of the constructor, no _val required?
<joelr>
but then how do i register it with the gc? just caml_register_global_root(Field(v, 0))?
Submarine has joined #ocaml
mort___ has joined #ocaml
Hussaind has quit [Quit: Konversation terminated!]
ocp has quit [Ping timeout: 272 seconds]
iago has joined #ocaml
ulfdoz has joined #ocaml
Anarchos has joined #ocaml
Tobu has quit [Ping timeout: 272 seconds]
Tobu has joined #ocaml
err404 has joined #ocaml
tmaeda is now known as tmaedaZ
BiDOrD_ has joined #ocaml
<joelr>
is ocaml float a full double in c?
<thelema>
joelr: yes
<joelr>
thanks
BiDOrD has quit [Ping timeout: 260 seconds]
rwmjones has quit [Ping timeout: 255 seconds]
<joelr>
do i need to allocate a block to return a double (float in ocaml)?
<thelema>
yes
<adrien>
iirc, caml_copy_double will do what you need
<joelr>
thelema: so i can't just do CAMLreturn(Double_val(d))?
<joelr>
adrien: thanks, that's awesome!
<adrien>
there's no Double_val :P
<thelema>
:)
<adrien>
(there's caml_copy_double instead)
<joelr>
ok
<joelr>
actually
<joelr>
there's Double_val in mlvalues
<adrien>
I guess the Val_ and _val macros don't allocate, and that's probably the criterium for their naming
<adrien>
argh, it's the other way round
<adrien>
there's no Val_double, there's caml_copy_double instead
<joelr>
ok
<adrien>
but Double_val was not the function you wanted: it gives a "double" from a "value"
<joelr>
right
<joelr>
i wish i could eliminate all that conversion boilerplate
_andre has quit [Quit: leaving]
<thelema>
joelr: I've had some ideas for having this taken care of on the compiler side, by declaring C types for arguments and return value of external functions...
<joelr>
thelema: i think it could be handled with c++ templates
<thelema>
This would only work for types that the compiler knows the conversion routines for
maufred_ has quit [Read error: Operation timed out]
rwmjones has joined #ocaml
<adrien>
thelema: phantom types for C? :-)
eni has joined #ocaml
Submarine has quit [Remote host closed the connection]
<thelema>
adrien: no, just auto-generated per-parameter conversion, to hook directly with a C function without writing any C
<mrvn>
joelr: So when allocating the C side you allocate a block of size 50, initialize with e.g. Val_unit and add that as GC root.
<NihilistDandy>
I need a case for Fix, obviously, but this is closer to what I'm going for
<mrvn>
joelr: and then you return a custom block containing a pointer to the block and any other C data with a finalizer that will unregister the GC root.
<joelr>
mrvn: do you mean here? v = caml_alloc_custom(&ops, sizeof(MyCallbacks*), 0, 1);
<joelr>
mrvn: i don't understand the part about allocating a block of size 50. are you saying i don't need my array of values?
<mrvn>
joelr: No. Add an indirection. Put all the ocaml values in a normal ocaml block and add the address of that block in your custom block.
<joelr>
mrvn: i'm already storing the c++ object pointer in the custom block, though
<mrvn>
struct MyData { value callbacks[50]; int whatever; char *foo; } in your custom block.
<mrvn>
joelr: Only important part is that you keep the "type callbacks = INIT ... | FOO ... | BAR ..." in sync with the C enum callbacks { INIT, FOO, BAR, ... }
<joelr>
of course
<Ptival>
NihilistDandy: that's what I would have done
<mrvn>
joelr: I always wondered if one couldn't generate the enum from the ocaml type with some preprocessor magic.
<joelr>
yeah
<mrvn>
joelr: Or a mixture of camlp4 and cpp so one source works for both.
<NihilistDandy>
Cool. I think all that leaves is the Fix case of Appl (at least I think I need such a thing) and I'm pretty sure I'll be done.
<mrvn>
camlp4 would filter out the C parts and cpp the ocaml parts in the declaration of the ocaml type / C enum
<joelr>
could work
<Anarchos>
mrvn or use sed or m4
<mrvn>
Or could one use camlp4 to generate a .h file as a byproduct of compiling the ml(i) file?
<Anarchos>
mrvn for sources in both languages, i use noweb, a literate programming tool :)
<mrvn>
Anarchos: gcc calls cpp, not sed or m4
<NihilistDandy>
Oh, actually, that may be unnecessary on the static side, since it's only defined on values.
<mrvn>
NihilistDandy: you can probably just mak the constructors tag to the array position.
<mrvn>
s/mak/map/
<Anarchos>
mrvn did you tried the output-obj option ?
<mrvn>
Anarchos: Haven't tried anything.
<mrvn>
I have never even written my camlp4 stuff
<Anarchos>
mrvn me neither
joelr has quit [Quit: joelr]
<Ptival>
NihilistDandy: I think FixAppl is only about evaluation, not typing
<Ptival>
it's a big-step reduction rule
<NihilistDandy>
Right
<NihilistDandy>
Though I just realized I think my Let case is broken
<NihilistDandy>
Trying to figure out if I just stopped mid thought or if I messed up something else
<Ptival>
it looks right afaict
<NihilistDandy>
Hmm. I wonder what the error is, then
<NihilistDandy>
"This pattern matches values of type Tdast.expr
<NihilistDandy>
but a pattern was expected which matches values of type Tdast.dtype"
<Anarchos>
NihilistDandy no more code available ?
<NihilistDandy>
Anarchos: This is the full code as posted. I'll make an annotation with the now corrected stuff. http://hpaste.org/68032