I was writing a simple parser function that expects an item in a stream, and returns an int, but for some reason the compiler keeps expecting a float for reasons I can't comprehend; especially considering that the code is actually example code from the llvm ocaml tutorial.
I've tried type casting both variables to ints, and just generally fiddling around with the syntax, but the function is so simple I can't figure out what's actually wrong. I know that one can, for a normal function, specify the type with let: type->type but I don't know how that would work with a parser function.
here's the function:
let parse_binary_precedence = parser
| [< 'Token.Number n >] -> int_of_float n
| [< >] -> 30
in
Here's the greater context of where it is used in case that is also part of the problem (although, I don't think it is):
let parse_binary_precedence = parser
| [< 'Token.Number n >] -> (int_of_float n)
| [< >] -> 30
in
parser
| [< (prefix, kind)=parse_operator;
'Token.Kwd op ?? "expected operator";
prec = parse_binary_precedence;
'Token.Kwd '(' ?? "expected '(' in operator prototype";
args = parse_first_arg [];
'Token.Kwd ')' ?? "expected ')' in operator protoype" >] ->
I currently am just getting the standard
File "parser.ml", line 108, characters 49-50:
Error: This expression has type int but an expression was expected of type
float
type error.
Does anybody know why this is expecting a float? How do I make the function expect an int?
EDIT:
I realize now that i've phrased it poorly now, but I realize that the context of the program is what decides the type of the function, I was asking about what within the program was making it assume that the function returned an int. It seems that it is outside of the scope of what i posted, so I'm updating my post with the code relating to everything shown.
Here is the full set of the relevant code. apologies for not including this to begin with.
token.ml:
type token =
(*primary*)
| Ident of string | Number of int
(*control*)
| If | Else | For
(*user ops*)
| Binary | Unary
parser.ml
let parse_prototype =
let rec parse_args accumulator = parser
| [< 'Token.Kwd ','; 'Token.Ident id; e=parse_args (id :: accumulator) >] -> e
| [< >] -> accumulator
in
let parse_first_arg accumulator = parser
| [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
| [< >] -> accumulator
in
let parse_operator = parser
| [< 'Token.Binary >] -> "binary", 2
| [< 'Token.Unary >] -> "unary", 1
in
let parse_binary_precedence = parser
| [< 'Token.Number n >] -> (int_of_float n) (*line 108*)
| [< >] -> 30
in
parser
| [< 'Token.Ident id;
'Token.Kwd '(' ?? "expected '(' in prototype";
args= parse_first_arg [];
'Token.Kwd ')' ?? "expected closing ')' in prototype " >] ->
Ast.Prototype (id, Array.of_list (List.rev args))
| [< (prefix, kind)=parse_operator;
'Token.Kwd op ?? "expected operator";
prec = parse_binary_precedence;
'Token.Kwd '(' ?? "expected '(' in operator prototype";
args = parse_first_arg [];
'Token.Kwd ')' ?? "expected ')' in operator protoype" >] ->
let name = prefix ^ (String.make 1 op) in
let args = Array.of_list (List.rev args) in
(*verify right number of args for op*)
if Array.length args != kind then
raise (Stream.Error "invalid number of operands in op def")
else
if kind == 1 then
Ast.Prototype (name, args)
else
Ast.BinOpPrototype (name, args, prec)
| [< >] ->
raise (Stream.Error "expected func name in prototype")
ast.ml
type proto =
| Prototype of string * string array
| BinOpPrototype of string * string array * int
Well, it is impossible to tell you where your code went wrong since you're not showing you code, but I can at least point you on your conceptual misunderstanding of how OCaml works, hoping that it will help you to fix your code :)
In OCaml, there is no typecasting and you can't make a function to expect anything, because types are inferred from the code that you have written.
For example, here is a function
it's type is inferred as
string -> intand under no circumstances, you can change it, because the type is fundamentally defined by the structure of your code. It is the compiler that infers the most general context in which your function/expression is applicable.In our example, the compiler knows that
String.countaccepts a value of typestringthereforesmust be also of typestring, it knows thatString.countreturns a value of typeintand that(+)could be applied only to integers. Therefore, the returned type isintand nothing more.If you will apply your function in an unacceptable context,
the compiler us, that the expression
number_of_words "hello, world"has typeintbut it is expected to have typestring. And this is not because our expression is wrong, it is because we're using it in a wrong context, in a context where astringis expected, sointjust doesn't fit it. The same is in your case, you're usingprecin the place where afloatvalue is expected. In other words, you're trying to fix in the wrong place.Going back to our example, the correct expression will be
Here
string_of_floatis not a coercion operator, not a type casting operator, nothing like this exists in OCaml, as otherwise, it will be unsound. It is a function that translates a value of typeintinto a value of typestring, i.e., it creates a new string and then fills it in with decimal digits the correspond to the number, e.g.,returns a string with two characters, not an integer, casted into a string.
Hope it helps. Also, it would be a good idea to take some tutorials in OCaml, before playing with OCaml Kaleidoscope, which is a pretty advanced, outdated, and very non-idiomatic example of OCaml programming.