orangeduck / BuildYourOwnLisp

Learn C and build your own programming language in under 1000 lines of code!
http://www.buildyourownlisp.com/
Other
2.9k stars 394 forks source link

Print statement not working while evaluating file #170

Closed rawhuul closed 2 years ago

rawhuul commented 2 years ago

Hey, there! I really appreciate the work you've done for mpc and Build Your Own Lisp book. Recently, I read the book and tried it out myself. Yesterday, I completed the 14th chapter of book which deals with strings, adding comments and print, error and load function as builtin types. And I tried it out and everything seems to work fine except whenever I try to evaluate a file, it doesn't output any thing at all whereas I am using print function and doing same thing in interpreter does work fine. Here, I am attaching a screenshot too.

Screenshot from 2022-02-09 12-27-49

As you can see in the following screenshot, in terminal while evaluating file it doesn't output anything whereas in interpreter it does.

Here is what my code looks like:-

int main(int argc, char **argv) {
  if (argc == 1) {
    eval(); // Here eval function will open a command line interface to interact with language.
  } else if (!strcmp(argv[1], "--version") || !strcmp(argv[1], "-v")) {
    printf("%s %s\n", PROG_NAME, VERSION);
  } else if (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) {
    printf("%s %s\n%s\n", PROG_NAME, VERSION, HELP_TEXT);
  } else if (!strcmp(argv[1], "--file") || !strcmp(argv[1], "-f")) {
    eval_file(argc, argv);
  }

  return 0;
}
void eval_file(int argc, char **argv) {
  parser *p = parse();
  lenv *env = lenv_new();
  lenv_add_builtins(env);
  for (int i = 2; i < argc; ++i) {
    lval *args = lval_add(lval_sexpr(), lval_str(argv[i]));
    lval *x = builtin_load(env, args, p->Yippy);

    if (x->type == LVAL_ERR) {
      lval_println(x);
    }
    lval_del(x);
  }
  lenv_del(env);
  p = parse_clean(p);
}

Here my eval_file function calls parse, builtin_load and parse_clean functions and other than those functions, everything is same as book describes.

My parser struct:

typedef struct parser {
  mpc_parser_t *Comments;
  mpc_parser_t *Number;
  mpc_parser_t *String;
  mpc_parser_t *Symbol;
  mpc_parser_t *Sexpr;
  mpc_parser_t *Qexpr;
  mpc_parser_t *Expr;
  mpc_parser_t *Yippy;
} parser;

My grammer:

#define GRAMMER                                                                \
  "                                          \
    comments : /;[^\\r\\n]*/ ;                      \
    number : /-?[0-9]+/ ;                       \
    symbol : /[a-zA-Z0-9_+\\-*%&|\\/\\\\=<>!~\"]+/;         \
    string  : /\"(\\\\.|[^\"])*\"/ ;                    \
    sexpr  : '(' <expr>* ')' ;                      \
    qexpr  : '{' <expr>* '}' ;                      \
    expr   : <comments> | <number> | <string>               \
            | <symbol> | <qexpr> | <sexpr> ;                \
    yippy  : /^/ <expr>* /$/ ;                      \
  "

parse function:

parser *parse() {
  parser *to_parse = (parser *)malloc(sizeof(parser));
  to_parse->Comments = mpc_new("comments");
  to_parse->Number = mpc_new("number");
  to_parse->String = mpc_new("string");
  to_parse->Symbol = mpc_new("symbol");
  to_parse->Sexpr = mpc_new("sexpr");
  to_parse->Qexpr = mpc_new("qexpr");
  to_parse->Expr = mpc_new("expr");
  to_parse->Yippy = mpc_new("yippy");

  mpca_lang(MPCA_LANG_DEFAULT, GRAMMER, to_parse->Comments, to_parse->Number,
            to_parse->String, to_parse->Symbol, to_parse->Sexpr,
            to_parse->Qexpr, to_parse->Expr, to_parse->Yippy);

  return to_parse;
}

My parse_clean function:

parser *parse_clean(parser *to_free) {
  mpc_cleanup(8, to_free->Comments, to_free->Number, to_free->String,
              to_free->Symbol, to_free->Sexpr, to_free->Qexpr, to_free->Expr,
              to_free->Yippy);
  free(to_free);
  to_free = NULL;
  return to_free;
}

builtin_load function:

lval *builtin_load(lenv *env, lval *a, mpc_parser_t *yippy) {
  LASSERT_NUM("load", a, 1);
  LASSERT_TYPE("load", a, 0, LVAL_STR);

  mpc_result_t r;
  if (mpc_parse_contents(a->cell[0]->string, yippy, &r)) {

    lval *expr = lval_read(r.output);
    mpc_ast_delete(r.output);

    while (expr->count) {
      lval *x = lval_eval(env, lval_pop(expr, 0));
      if (x->type == LVAL_ERR) {
        lval_println(x);
      }
      lval_del(x);
    }

    lval_del(expr);
    lval_del(a);

    return lval_sexpr();
  } else {
    char *error_msg = mpc_err_string(r.error);
    mpc_err_delete(r.error);
    lval *err = lval_err("Could not load library %s", error_msg);
    free(error_msg);
    lval_del(a);

    return err;
  }
}
orangeduck commented 2 years ago

Hi, not sure what could be wrong. I would suggest checking out what the expression it parses looks like in case something is wrong there.

rawhuul commented 2 years ago

Actually, parsed expression is correct.

rawhuul commented 2 years ago

Thanks for your response, it was my silly mistakes. I just fixed it. 🖤