Reputation: 1
I get the error below and I cannot figure out why this is the case. any help is appreciated. the program is an interpreter in Ocaml. The piece of code being underlined by tryOcaml is the last bit of code "processor tokens [];;" Not sure why that would be the type mismatch or where the mismatch happens in the code.
Error: This expression has type stackValue list but an expression was expected of type unit
type stackValue = NUM of int | BOOL of bool | ERROR | STRING of string | NAME of string | UNIT
type com = PUSH of stackValue | POP | ADD | SUB | MUL | DIV | REM | NEG | SWAP | QUIT | TOSTRING | PRINTLN (*| CAT | AND | OR | NOT | LESSTHAN | EQUAL | IF | BIND let com {com} end | funBind com {com} [return] funEnd | call*)
let interpreter ( (inFile : string), (outFile : string )) : unit =
let ic = open_in inFile
in
let oc = open_out outFile
in
let rec loop_read acc =
try
let l = String.trim(input_line ic) in loop_read (l::acc)
with
| End_of_file -> List.rev acc
in
let ls_str = loop_read []
in
let checkrest s =
match s.[0] with
| '"' -> if s.[(String.length s) -1]='"' then STRING(String.sub s 1 ((String.length s)-2)) else ERROR
| '-' | '0'..'9' -> (try NUM(int_of_string s) with _ ->ERROR)
| '_' | 'a'..'z' | 'A'..'Z' -> NAME(s)
|_ -> ERROR
in
let str2sv s =
match s with
|":true:" -> BOOL(true)
|":false:" -> BOOL(false)
|":unit:" -> UNIT
|":error:" -> ERROR
|_-> checkrest s
in
let str2com s =
match s with
|"quit" -> QUIT
|"add" -> ADD
|"sub" -> SUB
|"mul" -> MUL
|"div" -> DIV
|"rem" -> REM
|"pop" -> POP
|"neg" -> NEG
|"swap" -> SWAP
(*|"cat" -> CAT
|"and" -> AND
|"or" -> OR
|"not" -> NOT
|"lessthan" -> LESSTHAN
|"equal" -> EQUAL
|"if" -> IF
|"bind" -> BIND*)
|"toString" -> TOSTRING
|_ -> if String.sub s 0 4 = "push" then let x = str2sv (String.sub s 5 ((String.length s) -5)) in PUSH(x) else PUSH(ERROR)
in
let tokens = List.map str2com ls_str
in
let sv2str sv =
match sv with
|BOOL(true) -> STRING(":true:")
|BOOL(false) -> STRING(":false:")
|UNIT -> STRING(":unit:")
|ERROR -> STRING(":error:")
|STRING(s) -> STRING(s)
|NAME(s) -> STRING(s)
|NUM(x) -> STRING(string_of_int(x))
in
let file_write value = Printf.fprintf oc "%s\n" value
in
let rec processor comlist stack =
match (comlist,stack) with
|(PUSH(x)::comst, stack) -> processor comst (x::stack)
|(POP::comst, stackValue::reststack) -> processor comst reststack
|(POP::comst, []) -> processor comst (ERROR::stack)
|(ADD::comst, NUM(a)::NUM(b)::reststack) -> processor comst (NUM(a+b)::reststack)
|(ADD::comst, stack) -> processor comst (ERROR::stack)
|(SUB::comst, NUM(a)::NUM(b)::reststack) -> processor comst (NUM(b-a)::reststack)
|(SUB::comst, stack) -> processor comst (ERROR::stack)
|(MUL::comst, NUM(a)::NUM(b)::reststack) -> processor comst (NUM(a*b)::reststack)
|(MUL::comst, stack) -> processor comst (ERROR::stack)
|(DIV::comst, NUM(a)::NUM(b)::reststack) -> if (NUM(a)=NUM(0)) then (processor comst (ERROR::NUM(a)::NUM(b)::reststack)) else (processor comst (NUM(b/a)::reststack))
|(DIV::comst, stack) -> processor comst (ERROR::stack)
|(REM::comst, NUM(a)::NUM(b)::reststack) -> if (NUM(a)=NUM(0)) then (processor comst (ERROR::NUM(a)::NUM(b)::reststack)) else (processor comst (NUM(b mod a)::reststack))
|(REM::comst, stack) -> processor comst (ERROR::stack)
|(NEG::comst, NUM(a)::reststack) -> processor comst (NUM(-a)::reststack)
|(NEG::comst, stack) -> processor comst (ERROR::stack)
|(SWAP::comst, x::xs::reststack) -> processor comst (xs::x::reststack)
|(SWAP::comst, stack) -> processor comst (ERROR::stack)
|(TOSTRING::comst, x::reststack) -> let s = sv2str x in processor comst (s::reststack)
|(TOSTRING::comst, []) -> processor comst (ERROR::stack)
|(PRINTLN::comst, x::reststack) -> (match x with
|STRING(x) -> file_write x; processor comst reststack
|_ -> ERROR::stack)
|(PRINTLN::comst, []) -> processor comst (ERROR::stack)
|(QUIT::comst, stack) -> []
|(_,_) -> []
in
processor tokens [];;
Upvotes: 0
Views: 148
Reputation: 35210
Let me minimize your code to highlight the problem,
let interpreter ( (inFile : string), (outFile : string )) : unit =
... <snip> ...
let rec processor comlist stack =
match (comlist,stack) with
|(PUSH(x)::comst, stack) -> processor comst (x::stack)
|(QUIT::comst, stack) -> []
... <snip> ...
|(_,_) -> []
in
processor tokens []
Take a second and look carefully at the snippet above, do you see the problem? If not yet, then answer the following questions:
processor
function return?interpreter
shall return?E.g., consider processor [] []
, it will return []
therefore we can see that processor tokens []
is a value of type _ list
, but you have an annotation : unit
that says that your interpreter input output
shall evaluate to a value of type unit
where instead it evaluates to a stack.
If you really don't need the stack, you can ignore it,
ignore (processor tokens [])
where ignore
is a simple function, that has roughly the following implementation,
let ignore x = ()
i.e., it just ignores its argument so that it has type 'a -> unit
. Instead of using ignore
you can also write,
let _stack = processor tokens [] in
()
So you ignore the returned stack (the convention is to prefix with an underscope an ignored value) and return the ()
value instead of the _stack
.
Upvotes: 1