Fundamentals 9 min read

Implementing Value Storage and Error Handling in a C Lisp Interpreter

This article explains how to create a Lispy Value storage system in C, defining numeric and error types, enumerations, constructors, printing functions, and semantic error detection to support a simple Lisp REPL that evaluates Polish notation expressions.

AI Cyberspace
AI Cyberspace
AI Cyberspace
Implementing Value Storage and Error Handling in a C Lisp Interpreter

Value Storage in Lispy Interpreter

After implementing a Polish notation parser, we need a value storage called Lispy Values to hold AST values and error states.

Value Types

We define two value types: numeric operands and error messages.

typedef struct {
  int type;
  long num;
  int err;
} lval;

Enumeration for value types:

enum { LVAL_NUM, LVAL_ERR };

Enumeration for error types:

enum { LERR_DIV_ZERO, LERR_BAD_OP, LERR_BAD_NUM };

Constructors

lval lval_num(long x) {
  lval v;
  v.type = LVAL_NUM;
  v.num = x;
  return v;
}

lval lval_err(int x) {
  lval v;
  v.type = LVAL_ERR;
  v.err = x;
  return v;
}

Printing Functions

void lval_print(lval v) {
  switch (v.type) {
    case LVAL_NUM:
      printf("%li", v.num);
      break;
    case LVAL_ERR:
      if (v.err == LERR_DIV_ZERO) printf("Error: Division By Zero!");
      else if (v.err == LERR_BAD_OP) printf("Error: Invalid Operator!");
      else if (v.err == LERR_BAD_NUM) printf("Error: Invalid Number!");
      break;
  }
}

void lval_println(lval v) {
  lval_print(v);
  putchar('
');
}

Semantic Error Detection

During evaluation we propagate errors and check for division by zero, unknown operators, and invalid numbers.

lval eval_op(lval x, char *op, lval y) {
  if (x.type == LVAL_ERR) return x;
  if (y.type == LVAL_ERR) return y;
  if (strcmp(op, "+") == 0) return lval_num(x.num + y.num);
  if (strcmp(op, "-") == 0) return lval_num(x.num - y.num);
  if (strcmp(op, "*") == 0) return lval_num(x.num * y.num);
  if (strcmp(op, "/") == 0) {
    if (y.num == 0) return lval_err(LERR_DIV_ZERO);
    return lval_num(x.num / y.num);
  }
  return lval_err(LERR_BAD_OP);
}

The main evaluation function walks the AST, evaluates sub‑expressions, and combines them using eval_op. The main function sets up the parsers, reads input, parses, evaluates, prints the result, and cleans up.

CError HandlinginterpreterLispvalue storage
AI Cyberspace
Written by

AI Cyberspace

AI, big data, cloud computing, and networking.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.