Skip to content

Instantly share code, notes, and snippets.

@matthew-ball
Created January 3, 2017 07:35
Show Gist options
  • Save matthew-ball/198bb643223c1c08099cd564d01f6149 to your computer and use it in GitHub Desktop.
Save matthew-ball/198bb643223c1c08099cd564d01f6149 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef enum { BOOLEAN, CHARACTER, STRING, NUMBER, SYMBOL } object_type;
typedef union {
struct { char value; } boolean;
struct { char value; } character;
struct { char *value; } string;
struct { long value; } number;
struct { char *value; } symbol;
} object_data;
typedef struct {
object_type type;
object_data data;
} object;
#define IS_BOOLEAN(object) ((object)->type == BOOLEAN)
#define IS_CHARACTER(object) ((object)->type == CHARACTER)
#define IS_STRING(object) ((object)->type == STRING)
#define IS_NUMBER(object) ((object)->type == NUMBER)
#define IS_SYMBOL(object) ((object)->type == SYMBOL)
#define BOOLEAN_VALUE(object) ((object)->data.boolean.value)
#define CHARACTER_VALUE(object) ((object)->data.character.value)
#define STRING_VALUE(object) ((object)->data.string.value)
#define NUMBER_VALUE(object) ((object)->data.number.value)
#define SYMBOL_VALUE(object) ((object)->data.symbol.value)
object *true;
object *false;
#define IS_TRUE(object) ((object) == true)
#define IS_FALSE(object) (!IS_TRUE(object))
#define MALLOC_CHECK(ptr) ({ if ((ptr) == NULL) { fprintf(stderr, "[%s] malloc failed\n", __func__); exit(EXIT_FAILURE); } })
object *allocate_object() {
object *ptr = malloc(sizeof(object));
MALLOC_CHECK(ptr);
return ptr;
}
object *make_boolean(int value) {
object *ptr = allocate_object();
ptr->type = BOOLEAN;
BOOLEAN_VALUE(ptr) = value;
return ptr;
}
object *make_character(char value) {
object *ptr = allocate_object();
ptr->type = CHARACTER;
CHARACTER_VALUE(ptr) = value;
return ptr;
}
object *make_string(const char *value) {
object *ptr = allocate_object();
ptr->type = STRING;
STRING_VALUE(ptr) = malloc(strlen(value) + 1);
MALLOC_CHECK(STRING_VALUE(ptr));
strcpy(STRING_VALUE(ptr), value);
return ptr;
}
object *make_number(long value) {
object *ptr = allocate_object();
ptr->type = NUMBER;
NUMBER_VALUE(ptr) = value;
return ptr;
}
void print_object(const object *obj) {
switch (obj->type) {
case BOOLEAN:
printf("#%c", IS_TRUE(obj) ? 't' : 'f');
break;
case CHARACTER: {
char c = CHARACTER_VALUE(obj);
printf("#\\");
switch (c) {
case '\n':
printf("newline");
break;
case ' ':
printf("space");
break;
default:
putchar(c);
}
break;
}
case STRING: {
char *string = STRING_VALUE(obj);
putchar('"');
while ((*string) != '\0') {
switch (*string) {
case '\n':
printf("\\n");
break;
case '\\':
printf("\\\\");
break;
case '"':
printf("\\\"");
break;
default:
putchar(*string);
}
string++;
}
putchar('"');
break;
}
case NUMBER:
printf("%d", NUMBER_VALUE(obj));
break;
case SYMBOL:
printf("%s", SYMBOL_VALUE(obj));
break;
default:
fprintf(stderr, "unknown type\n");
exit(EXIT_FAILURE);
}
}
object *read_object(FILE *input) {
int c;
c = getc(input);
if (c == '#') {
c = getc(input);
switch (c) {
case 't':
return true;
case 'f':
return false;
}
}
return false;
}
object *evaluate_object(object *obj) {
return obj;
}
void repl(FILE *input) {
do {
printf("evaluate> ");
print_object(evaluate_object(read_object(input)));
printf("\n");
} while (1);
}
int main(int argc, char *argv[]) {
true = make_boolean(1);
false = make_boolean(0);
/* print_object(true); */
/* print_object(false); */
/* print_object(make_character('a')); */
/* print_object(make_string("string")); */
/* print_object(make_number(1)); */
repl(stdin);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment