【问题标题】:Why do I keep getting a match_failure?为什么我不断收到 match_failure?
【发布时间】:2015-05-03 02:35:19
【问题描述】:

我目前正在为 ocaml 中的 c flat 编写解释器。我得到了一个包含抽象语法树文件、主文件等的源代码生成文件。我正在尝试实现算术,但在运行测试用例时我不断收到此错误(match_failure)。测试用例位于 .cf 文件中。这是文件的内容 “print_int((9+6+(11/11)+1+(-6))*(-1));” 有人可以帮我理解为什么会发生错误吗?

这是我的代码:

open Ast;;
open Env;;
open Store;;

let allocateMem env = env;; (* TODO: implement this function *)


let rec eval_expr (expr:expr) (ps:proc_state) (env:environment) (store:store) : int = match expr with
      Add (e1, e2) -> 
      let r1 = eval_expr e1 ps env store in
      let r2 = eval_expr e2 ps env store in
      r1 + r2
  |  Sub (e1, e2) ->
      let r1 = eval_expr e1 ps env store in
      let r2 = eval_expr e2 ps env store in
      r1 - r2
  |  Mul (e1, e2) ->
      let r1 = eval_expr e1 ps env store in
      let r2 = eval_expr e2 ps env store in
      r1 * r2
  |  Div (e1, e2) ->
      let r1 = eval_expr e1 ps env store in
      let r2 = eval_expr e2 ps env store in
      r1 / r2
  |  Neg (e1) ->
      let r1 = eval_expr e1 ps env store in
      r1 * -1
  | IntConst i -> i
  | Id (e1) ->
      let l = binding_of env e1 in
      let Intval(i)= value_at(store,l) in
      i;;

;;

(* eval_expr: expr -> proc_state -> env -> store -> value *)
let rec eval_cond cond ps env store = match cond with
  Equal (e1, e2) ->
    let r1 = eval_expr e1 ps env store in
    let r2 = eval_expr e2 ps env store in
    r1 == r2
(* TODO: add more *)
;;

type stmtEvalRes = Next | BreakOut | ContinueOn;;

(* eval_stmt: stmt -> proc_state -> env -> store -> stmtEvalRes*proc_state *)
let rec eval_stmt stmt ps env store = match stmt with
| PrintInt e ->
    let r = eval_expr e ps env store in
    print_int r; (Next, ps, store)
| PrintStr s ->
    print_string (Str.global_replace (Str.regexp "\\\\n") "\n" s); 
    (* Escaping characters here because it's not done in the parser *)
    (Next, ps, store)
| List (stmt1::stmts) -> eval_stmt stmt1 ps env store
  (* TODO: complete this case so that all statements in the list evaluated *)
;;

【问题讨论】:

  • 请发布足够的代码来重现错误。还请发布您在编译代码时收到的任何编译器警告。
  • 我更新了。另外,我没有收到任何警告。
  • 如果您遇到匹配失败,我不明白这怎么可能是真的 - 除非您明确禁用详尽警告。请注意,如果您在不更改代码或运行 make clean 的情况下运行 make 将不会收到任何警告,因为它不会编译任何未更改的文件。
  • 无论如何,当我说“重现错误”时,我的意思是“编译你的代码,运行它并得到与你相同的错误”。当我尝试运行您的代码时,我收到一堆关于未定义类型和构造函数的编译错误。很明显,这不足以重现错误。如果您可以将问题减少到包含所有相关定义的单个文件,可以编译和运行并在运行时产生相同的错误消息(同时希望通过删除与错误而不破坏程序)。
  • 我做了 make clean 然后 make all ,我得到了这个警告:“警告 8:这个模式匹配并不详尽。这是一个不匹配的值的例子:(Sub (, _)|Mul (, )|Div (, )|Neg _|Id _|At (, )|Deref _ |AddressOf _| 调用 (, _)|Pre _|Post _) "

标签: pattern-matching ocaml match


【解决方案1】:

根据警告,我们可以重构expr类型,有如下一组构造函数:Add, Sub, Mul,Div, Neg, Id, At, Deref, AddressOf, Call, Pre, Post,即11个分支,你只有7个。

我怀疑,您作为作业获得的原始代码具有以下实现:

let rec eval_expr (expr:expr) (ps:proc_state) (env:environment) (store:store) : int = match expr with
      Add (e1, e2) -> 
      let r1 = eval_expr e1 ps env store in
      let r2 = eval_expr e2 ps env store in
      r1 + r2
 (* TODO: add more *)

这就是为什么在编译原始代码时会收到警告:

Warning 8: this pattern-matching is not exhaustive. 
Here is an example of a value that is not matched: 
(Sub (, _)|Mul (, )|Div (, )|Neg _|Id _|At (, )|Deref _|AddressOf _| Call (, _)|Pre _|Post _) "

您向我们展示的代码不是您尝试编译的代码。也许你在顶层玩它。

正如 sepp2k 提到的,测试表达式不包含调用表达式,这意味着您很有可能正在编译和运行原始代码,即仅包含一个 Add 分支的代码,而不是代码,你写的。这就是为什么你会遇到匹配失败。 (但迟早,你仍然需要编写所有 11 个分支)。

【讨论】:

  • 我很确定给定的表达式中没有调用。 print_int 几乎肯定会被解析为语句 PrintInt(参见 eval_stmnt)。
猜你喜欢
  • 2017-02-24
  • 2020-04-30
  • 2017-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-31
  • 2019-04-30
相关资源
最近更新 更多