qc/main.c

1781 lines
44 KiB
C

#include <stdarg.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <limits.h>
#include <gmp.h>
#include <readline/readline.h>
#include <readline/history.h>
#include "avl.h"
#define TODO assert(!"TODO");
#define argv0 program_invocation_name
#ifdef ZDEBUG
#define zprintf(fmt, ...) \
printf(fmt, ## __VA_ARGS__);
#else
#define zprintf(...);
#endif
const char* command = NULL;
static void parse_args(int argc, char* const* argv)
{
for (int opt; (opt = getopt(argc, argv, "c:")) != -1; ) switch (opt)
{
case 'c':
command = optarg;
break;
default:
{
printf("Unknown option '%c'!" "\n", opt);
exit(1);
break;
}
}
}
struct string
{
char* data;
unsigned refcount;
};
struct string* new_string(const char* data_ro)
{
struct string* this = malloc(sizeof(*this));
this->data = strdup(data_ro);
this->refcount = 1;
return this;
}
struct string* new_string_from_fmt(const char* fmt, ...)
{
struct string* this = malloc(sizeof(*this));
va_list ap;
va_start(ap, fmt);
int x = vasprintf(&this->data, fmt, ap);
if (x < 0)
{
abort();
}
this->refcount = 1;
va_end(ap);
return this;
}
struct string* inc_string(struct string* this)
{
if (this)
this->refcount++;
return this;
}
void free_string(struct string* this)
{
if (this && !--this->refcount)
{
free(this->data);
free(this);
}
}
struct value;
struct value* inc_value(struct value* this);
void free_value(struct value* this);
struct expression
{
enum expression_kind {
ek_syntax_error,
// primary:
ek_literal,
ek_variable,
// arithmetic operators:
ek_positive,
ek_negative,
ek_add,
ek_subtract,
ek_multiply,
ek_divide,
// comparision operators:
ek_greater_than,
ek_less_than,
ek_greater_than_equal_to,
ek_less_than_equal_to,
// equality operators:
ek_equal_to,
ek_not_equal_to,
// logical operators:
ek_logical_not,
ek_logical_and,
ek_logical_or,
ek_ternary,
ek_assign,
ek_comma,
} kind;
struct string* string;
struct expression* center;
struct expression* left;
struct expression* right;
struct value* value;
unsigned refcount;
};
struct expression* inc_expression(struct expression* this);
struct expression* new_syntax_error_expression(
struct string* error_message,
struct expression* subexpression)
{
struct expression* this = malloc(sizeof(*this));
this->kind = ek_syntax_error;
this->string = inc_string(error_message);
this->center = inc_expression(subexpression);
this->left = this->right = NULL;
this->value = NULL;
this->refcount = 1;
return this;
}
struct expression* new_literal_expression(
struct value* value)
{
struct expression* this = malloc(sizeof(*this));
this->kind = ek_literal;
this->string = NULL;;
this->center = NULL;
this->left = this->right = NULL;
this->value = inc_value(value);
this->refcount = 1;
return this;
}
struct expression* new_variable_expression(
struct string* variable)
{
struct expression* this = malloc(sizeof(*this));
this->kind = ek_variable;
this->string = inc_string(variable);
this->center = NULL;
this->left = this->right = NULL;
this->value = NULL;
this->refcount = 1;
return this;
}
struct expression* new_logical_not_expression(
struct expression* sub)
{
struct expression* this = malloc(sizeof(*this));
this->kind = ek_logical_not;
this->string = NULL;
this->center = inc_expression(sub);
this->left = NULL;
this->right = NULL;
this->value = NULL;
this->refcount = 1;
return this;
}
struct expression* new_positive_expression(
struct expression* sub)
{
struct expression* this = malloc(sizeof(*this));
this->kind = ek_positive;
this->string = NULL;
this->center = inc_expression(sub);
this->left = NULL;
this->right = NULL;
this->value = NULL;
this->refcount = 1;
return this;
}
struct expression* new_negative_expression(
struct expression* sub)
{
struct expression* this = malloc(sizeof(*this));
this->kind = ek_negative;
this->string = NULL;
this->center = inc_expression(sub);
this->left = NULL;
this->right = NULL;
this->value = NULL;
this->refcount = 1;
return this;
}
struct expression* new_binary_expression(
enum expression_kind kind,
struct expression* left,
struct expression* right)
{
struct expression* this = malloc(sizeof(*this));
this->kind = kind;
this->string = NULL;
this->center = NULL;
this->left = inc_expression(left);
this->right = inc_expression(right);
this->value = NULL;
this->refcount = 1;
return this;
}
struct expression* inc_expression(struct expression* this)
{
if (this)
this->refcount++;
return this;
}
void free_expression(struct expression* this)
{
if (this && !--this->refcount)
{
free_string(this->string);
free_expression(this->center);
free_expression(this->left);
free_expression(this->right);
free_value(this->value);
free(this);
}
}
struct value
{
mpq_t mpq;
unsigned refcount;
};
struct value* new_value_from_int(int x)
{
struct value* this = malloc(sizeof(*this));
mpq_init(this->mpq);
mpq_set_si(this->mpq, x, 1);
this->refcount = 1;
return this;
}
struct value* new_value(mpq_t mpq)
{
struct value* this = malloc(sizeof(*this));
mpq_init(this->mpq);
mpq_set(this->mpq, mpq);
this->refcount = 1;
return this;
}
struct value* inc_value(struct value* this)
{
if (this)
this->refcount++;
return this;
}
void free_value(struct value* this)
{
if (this && !--this->refcount)
{
mpq_clear(this->mpq);
free(this);
}
}
struct value* scan(const char* text)
{
const char* moving = text;
mpq_t base; mpq_init(base);
mpq_t tmp; mpq_init(tmp);
mpq_t value; mpq_init(value);
mpq_set_si(value, 0, 1);
mpq_set_si(base, 10, 1);
while ('0' <= *moving && *moving <= '9')
{
mpq_set_si(tmp, *moving++ - '0', 1);
mpq_mul(value, value, base);
mpq_add(value, value, tmp);
}
if (*moving == '.')
{
mpq_t factor; mpq_init(factor);
moving++;
mpq_set_si(factor, 1, 10);
while ('0' <= *moving && *moving <= '9')
{
mpq_set_si(tmp, *moving++ - '0', 1);
mpq_mul(tmp, factor, tmp);
mpq_add(value, value, tmp);
mpq_div(factor, factor, base);
}
mpq_clear(factor);
}
assert(!*moving);
struct value* retval = new_value(value);
mpq_clear(base);
mpq_clear(tmp);
mpq_clear(value);
return retval;
}
struct scope
{
avl_tree_t* tree;
};
struct variable
{
struct string* name;
struct value* value;
};
struct variable* new_variable(struct string* name)
{
struct variable* this = malloc(sizeof(*this));
this->name = inc_string(name);
this->value = NULL;
return this;
}
int compare_variable(const void* a, const void* b)
{
const struct variable* A = a, *B = b;
return strcmp(A->name->data, B->name->data);
}
void free_variable(void* ptr)
{
struct variable* this = ptr;
free_string(this->name);
free_value(this->value);
free(this);
}
struct scope* new_scope(void)
{
struct scope* this = malloc(sizeof(*this));
this->tree = avl_alloc_tree(compare_variable, free_variable);
return this;
}
struct value** scope_lookup(
struct scope* this,
struct string* name)
{
struct avl_node_t* node = avl_search(this->tree, &name);
if (!node)
{
struct variable* var = new_variable(name);
node = avl_insert(this->tree, var);
}
return &((struct variable*) node->item)->value;
}
void free_scope(struct scope* this)
{
avl_free_tree(this->tree);
free(this);
}
struct expression* parse(const char* text)
{
enum {
tk_uninitialized,
// primary:
tk_identifier,
tk_literal,
// brakets:
tk_oparen,
tk_cparen,
// arithmetic operators:
tk_plus,
tk_minus,
tk_asterisk,
tk_slash,
// comparision operators:
tk_less_than,
tk_less_than_eq,
tk_greater_than,
tk_greater_than_eq,
tk_emarkequals,
tk_equalsequals,
// logical operators:
tk_vbarvbar,
tk_ampersandampersand,
// misc:
tk_emark,
tk_qmark,
tk_colon,
tk_equals,
tk_comma,
tk_EOF,
number_of_tokens,
} tokenkind = tk_uninitialized;
static const char* const tokennames[number_of_tokens] = {
[tk_EOF] = "EOF",
[tk_identifier] = "identifier",
[tk_literal] = "literal",
[tk_oparen] = "(",
[tk_cparen] = ")",
[tk_plus] = "+",
[tk_minus] = "-",
[tk_asterisk] = "*",
[tk_slash] = "/",
[tk_less_than] = "<",
[tk_less_than_eq] = "<=",
[tk_greater_than] = ">",
[tk_greater_than_eq] = ">=",
[tk_emarkequals] = "!=",
[tk_equalsequals] = "==",
[tk_vbarvbar] = "||",
[tk_ampersandampersand] = "&&",
[tk_emark] = "!",
[tk_qmark] = "?",
[tk_colon] = ":",
[tk_equals] = "=",
[tk_comma] = ",",
};
struct {
char* data;
size_t n, cap;
} buffer = {};
void append(char c)
{
if (buffer.n == buffer.cap)
{
buffer.cap = buffer.cap << 1 ?: 1;
buffer.data = realloc(buffer.data, sizeof(*buffer.data) * buffer.cap);
}
buffer.data[buffer.n++] = c;
}
const char* moving = text;
void next_token(void)
{
while (*moving && *moving == ' ')
moving++;
switch (*moving)
{
case 0:
tokenkind = tk_EOF;
break;
case '0' ... '9':
{
buffer.n = 0;
while (false
|| *moving == '_'
|| *moving == '.'
|| ('0' <= *moving && *moving <= '9'))
{
append(*moving++);
}
append(0);
tokenkind = tk_literal;
break;
}
case '_':
case 'a' ... 'z':
case 'A' ... 'Z':
{
buffer.n = 0;
while (false
|| *moving == '_'
|| ('a' <= *moving && *moving <= 'z')
|| ('A' <= *moving && *moving <= 'Z'))
{
append(*moving++);
}
append(0);
tokenkind = tk_identifier;
break;
}
case '+': tokenkind = tk_plus, moving++; break;
case '-': tokenkind = tk_minus, moving++; break;
case '*': tokenkind = tk_asterisk, moving++; break;
case '/': tokenkind = tk_slash, moving++; break;
case '(': tokenkind = tk_oparen, moving++; break;
case ')': tokenkind = tk_cparen, moving++; break;
case '?': tokenkind = tk_qmark, moving++; break;
case ':': tokenkind = tk_colon, moving++; break;
case ',': tokenkind = tk_comma, moving++; break;
case '|':
{
moving++;
switch (*moving)
{
case '|':
tokenkind = tk_vbarvbar, moving++;
break;
default:
{
TODO;
break;
}
}
break;
}
case '&':
{
moving++;
switch (*moving)
{
case '&':
tokenkind = tk_ampersandampersand, moving++;
break;
default:
{
TODO;
break;
}
}
break;
}
case '!':
{
moving++;
switch (*moving)
{
case '=':
tokenkind = tk_emarkequals, moving++;
break;
default:
tokenkind = tk_emark;
break;
}
break;
}
case '<':
{
moving++;
switch (*moving)
{
case '=':
tokenkind = tk_less_than_eq, moving++;
break;
default:
{
tokenkind = tk_less_than;
break;
}
}
break;
}
case '>':
{
moving++;
switch (*moving)
{
case '=':
tokenkind = tk_greater_than_eq, moving++;
break;
default:
{
tokenkind = tk_greater_than;
break;
}
}
break;
}
case '=':
{
moving++;
switch (*moving)
{
case '=':
tokenkind = tk_equalsequals, moving++;
break;
default:
tokenkind = tk_equals, moving++;
break;
}
break;
}
default:
assert(!"TODO");
break;
}
}
next_token();
struct expression* parse_root(void)
{
struct expression* parse_comma(void)
{
struct expression* parse_assign(void)
{
struct expression* parse_ternary(void)
{
struct expression* parse_logicals(void)
{
struct expression* parse_equality(void)
{
struct expression* parse_comparision(void)
{
struct expression* parse_arithmetic(void)
{
struct expression* parse_prefix(void)
{
struct expression* parse_primary(void)
{
struct expression* retval;
switch (tokenkind)
{
case tk_identifier:
{
struct string* name =
new_string(buffer.data);
retval = new_variable_expression(name);
next_token();
free_string(name);
break;
}
case tk_literal:
{
struct value* value =
scan(buffer.data);
retval = new_literal_expression(value);
next_token();
free_value(value);
break;
}
case tk_oparen:
{
next_token();
retval = parse_root();
if (tokenkind != tk_cparen)
{
struct string* message =
new_string_from_fmt(
"unexpected '%s'",
tokennames[tokenkind]);
retval = new_syntax_error_expression(message, retval);
free_string(message);
}
next_token();
break;
}
default:
{
struct string* message =
new_string_from_fmt(
"unexpected '%s'",
tokennames[tokenkind]);
retval = new_syntax_error_expression(message, NULL);
free_string(message);
break;
}
}
return retval;
}
switch (tokenkind)
{
case tk_emark:
{
next_token();
struct expression* sub =
parse_prefix();
struct expression* retval =
new_logical_not_expression(sub);
free_expression(sub);
return retval;
}
case tk_plus:
{
next_token();
struct expression* sub =
parse_prefix();
struct expression* retval =
new_positive_expression(sub);
free_expression(sub);
return retval;
}
case tk_minus:
{
next_token();
struct expression* sub =
parse_prefix();
struct expression* retval =
new_negative_expression(sub);
free_expression(sub);
return retval;
}
default:
return parse_primary();
}
}
struct expression* left = parse_prefix();
again: switch (tokenkind)
{
case tk_plus:
{
next_token();
struct expression* right =
parse_prefix();
struct expression* retval =
new_binary_expression(ek_add, left, right);
free_expression(left);
free_expression(right);
left = retval;
goto again;
}
case tk_minus:
{
next_token();
struct expression* right =
parse_prefix();
struct expression* retval =
new_binary_expression(ek_subtract, left, right);
free_expression(left);
free_expression(right);
left = retval;
goto again;
}
case tk_asterisk:
{
next_token();
struct expression* right =
parse_prefix();
struct expression* retval =
new_binary_expression(ek_multiply, left, right);
free_expression(left);
free_expression(right);
left = retval;
goto again;
}
case tk_slash:
{
next_token();
struct expression* right =
parse_prefix();
struct expression* retval =
new_binary_expression(ek_divide, left, right);
free_expression(left);
free_expression(right);
left = retval;
goto again;
}
default:
break;
}
return left;
}
struct expression* left = parse_arithmetic();
again: switch (tokenkind)
{
case tk_less_than:
{
next_token();
struct expression* right =
parse_arithmetic();
struct expression* retval =
new_binary_expression(ek_less_than, left, right);
free_expression(left);
free_expression(right);
left = retval;
goto again;
}
case tk_less_than_eq:
{
next_token();
struct expression* right =
parse_arithmetic();
struct expression* retval =
new_binary_expression(ek_less_than_equal_to, left, right);
free_expression(left);
free_expression(right);
left = retval;
goto again;
}
case tk_greater_than:
{
next_token();
struct expression* right =
parse_arithmetic();
struct expression* retval =
new_binary_expression(ek_greater_than, left, right);
free_expression(left);
free_expression(right);
left = retval;
goto again;
}
case tk_greater_than_eq:
{
next_token();
struct expression* right =
parse_arithmetic();
struct expression* retval =
new_binary_expression(ek_greater_than_equal_to, left, right);
free_expression(left);
free_expression(right);
left = retval;
goto again;
}
default:
break;
}
return left;
}
struct expression* left = parse_comparision();
again: switch (tokenkind)
{
case tk_equalsequals:
{
next_token();
struct expression* right =
parse_comparision();
struct expression* retval =
new_binary_expression(ek_equal_to, left, right);
free_expression(left);
free_expression(right);
left = retval;
goto again;
}
case tk_emarkequals:
{
next_token();
struct expression* right =
parse_comparision();
struct expression* retval =
new_binary_expression(ek_not_equal_to, left, right);
free_expression(left);
free_expression(right);
left = retval;
goto again;
}
default:
break;
}
return left;
}
struct expression* left = parse_equality();
again: switch (tokenkind)
{
case tk_vbarvbar:
{
next_token();
struct expression* right =
parse_equality();
struct expression* retval =
new_binary_expression(ek_logical_or, left, right);
free_expression(left);
free_expression(right);
left = retval;
goto again;
}
case tk_ampersandampersand:
{
next_token();
struct expression* right =
parse_equality();
struct expression* retval =
new_binary_expression(ek_logical_and, left, right);
free_expression(left);
free_expression(right);
left = retval;
goto again;
}
default:
break;
}
return left;
}
struct expression* center = parse_logicals();
if (tokenkind == tk_qmark)
{
next_token();
struct expression* left = parse_logicals();
next_token();
struct expression* right = parse_logicals();
TODO;
}
else
{
return center;
}
}
struct expression* left = parse_ternary();
if (tokenkind == tk_equals)
{
next_token();
struct expression* right = parse_assign();
struct expression* retval = new_binary_expression(ek_assign, left, right);
free_expression(left);
free_expression(right);
return retval;
}
else
{
return left;
}
}
struct expression* left = parse_assign();
again: switch (tokenkind)
{
case tk_comma:
{
next_token();
struct expression* right = parse_assign();
struct expression* retval = new_binary_expression(ek_comma, left, right);
free_expression(left);
free_expression(right);
left = retval;
goto again;
}
default:
break;
}
return left;
}
return parse_comma();
}
struct expression* root = parse_root();
if (tokenkind != tk_EOF)
{
struct string* message = new_string_from_fmt(
"expected EOF, unexpected '%s'", tokennames[tokenkind]);
struct expression* error = new_syntax_error_expression(message, root);
free_expression(root);
root = error;
free_string(message);
}
free(buffer.data);
return root;
}
struct value** evaluate_lvalue(
struct expression* expression,
struct scope* scope)
{
switch (expression->kind)
{
case ek_syntax_error: assert(0); break;
case ek_variable:
{
return scope_lookup(scope, expression->string);
}
case ek_literal: TODO; break;
case ek_add: TODO; break;
case ek_subtract: TODO; break;
case ek_multiply: TODO; break;
case ek_divide: TODO; break;
case ek_positive: TODO; break;
case ek_negative: TODO; break;
case ek_greater_than: TODO; break;
case ek_greater_than_equal_to: TODO; break;
case ek_less_than: TODO; break;
case ek_less_than_equal_to: TODO; break;
case ek_equal_to: TODO; break;
case ek_not_equal_to: TODO; break;
case ek_logical_not: TODO; break;
case ek_logical_and: TODO; break;
case ek_logical_or: TODO; break;
case ek_ternary: TODO; break;
case ek_assign:
{
TODO;
break;
};
case ek_comma:
{
TODO;
break;
};
}
return NULL;
}
struct value* evaluate(
struct expression* expression,
struct scope* scope)
{
struct value* retval = NULL;
switch (expression->kind)
{
case ek_syntax_error: assert(0); break;
case ek_variable:
{
struct value* val = *scope_lookup(scope, expression->string);
if (val)
{
retval = inc_value(val);
}
else
{
retval = new_value_from_int(0);
}
break;
};
case ek_literal:
{
retval = inc_value(expression->value);
break;
}
case ek_add:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
mpq_t q;
mpq_init(q);
mpq_add(q, left->mpq, right->mpq);
retval = new_value(q);
free_value(left), free_value(right);
mpq_clear(q);
break;
}
case ek_subtract:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
mpq_t q;
mpq_init(q);
mpq_sub(q, left->mpq, right->mpq);
retval = new_value(q);
free_value(left), free_value(right);
mpq_clear(q);
break;
}
case ek_multiply:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
mpq_t q;
mpq_init(q);
mpq_mul(q, left->mpq, right->mpq);
retval = new_value(q);
free_value(left), free_value(right);
mpq_clear(q);
break;
}
case ek_divide:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
mpq_t q;
mpq_init(q);
mpq_div(q, left->mpq, right->mpq);
retval = new_value(q);
free_value(left), free_value(right);
mpq_clear(q);
break;
}
case ek_positive:
{
retval = evaluate(expression->center, scope);
break;
}
case ek_negative:
{
struct value* sub = evaluate(expression->center, scope);
mpq_t q;
mpq_init(q);
mpq_neg(q, sub->mpq);
retval = new_value(q);
free_value(sub);
mpq_clear(q);
break;
}
case ek_greater_than:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
retval = new_value_from_int(mpq_cmp(left->mpq, right->mpq) > 0);
free_value(left), free_value(right);
break;
}
case ek_greater_than_equal_to:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
retval = new_value_from_int(mpq_cmp(left->mpq, right->mpq) >= 0);
free_value(left), free_value(right);
break;
}
case ek_less_than:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
retval = new_value_from_int(mpq_cmp(left->mpq, right->mpq) < 0);
free_value(left), free_value(right);
break;
}
case ek_less_than_equal_to:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
retval = new_value_from_int(mpq_cmp(left->mpq, right->mpq) <= 0);
free_value(left), free_value(right);
break;
}
case ek_equal_to:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
retval = new_value_from_int(mpq_cmp(left->mpq, right->mpq) == 0);
free_value(left), free_value(right);
break;
}
case ek_not_equal_to:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
retval = new_value_from_int(mpq_cmp(left->mpq, right->mpq) != 0);
free_value(left), free_value(right);
break;
}
case ek_logical_not:
{
struct value* sub = evaluate(expression->center, scope);
retval = new_value_from_int(mpq_sgn(sub->mpq) == 0);
free_value(sub);
break;
}
case ek_logical_and:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
retval = new_value_from_int(
mpq_sgn(left->mpq) != 0 && mpq_sgn(right->mpq) != 0);
free_value(left), free_value(right);
break;
}
case ek_logical_or:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
retval = new_value_from_int(
mpq_sgn(left->mpq) != 0 || mpq_sgn(right->mpq) != 0);
free_value(left), free_value(right);
break;
}
case ek_ternary: TODO; break;
case ek_assign:
{
struct value** lvalue = evaluate_lvalue(expression->left, scope);
retval = evaluate(expression->right, scope);
free_value(*lvalue), *lvalue = inc_value(retval);
break;
};
case ek_comma:
{
free_value(evaluate(expression->left, scope));
retval = evaluate(expression->right, scope);
break;
};
}
return retval;
}
void print_mpz(const mpz_t x_ro, const char* digits[10])
{
assert(mpz_sgn(x_ro) > 0);
mpz_t x, d, b;
mpz_init(x), mpz_init(d), mpz_init(b);
mpz_set(x, x_ro);
mpz_set_ui(b, 10);
size_t n = mpz_sizeinbase(x, 10);
unsigned *buffer = malloc(sizeof(*buffer) * n);
unsigned *moving = buffer;
while (mpz_sgn(x))
{
mpz_fdiv_qr(x, d, x, b);
assert(mpz_fits_uint_p(d));
unsigned int diu = mpz_get_ui(d);
assert(diu < 10);
*moving++ = diu;
}
while (moving > buffer)
{
printf("%s", digits[*--moving]);
}
free(buffer);
mpz_clear(x), mpz_clear(d), mpz_clear(b);
}
void print(struct value* this)
{
mpq_t v;
mpq_init(v);
mpq_set(v, this->mpq);
if (mpq_sgn(v) == 0)
{
putchar('0');
}
else
{
if (mpq_sgn(v) < 0)
{
putchar('-');
mpq_abs(v, v);
}
mpz_t q;
mpz_init(q);
mpz_fdiv_q(q, mpq_numref(v), mpq_denref(v));
if (mpz_sgn(q) > 0)
{
print_mpz(q,
(const char*[10]){"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"});
putchar(' ');
}
mpq_t qq;
mpq_init(qq);
mpq_set_z(qq, q);
mpq_sub(v, v, qq);
if (mpq_sgn(v) > 0)
{
print_mpz(mpq_numref(v),
(const char*[10]){"", "¹", "²", "³", "", "", "", "", "", ""});
putchar('/');
print_mpz(mpq_denref(v),
(const char*[10]){"", "", "", "", "", "", "", "", "", ""});
}
mpq_clear(qq);
mpz_clear(q);
}
mpq_clear(v);
puts("");
}
void print_syntax_error(
const struct expression* this)
{
assert(this->kind == ek_syntax_error);
printf("syntax error: %s\n", this->string->data);
}
bool foreach_syntax_error(
struct expression* exp,
void (*callback)(
const struct expression*))
{
bool retval = false;
if (exp->kind == ek_syntax_error)
{
callback(exp);
retval = true;
}
if (exp->center && foreach_syntax_error(exp->center, callback))
{
retval = true;
}
if (exp->left && foreach_syntax_error(exp->left, callback))
{
retval = true;
}
if (exp->right && foreach_syntax_error(exp->right, callback))
{
retval = true;
}
return retval;
}
int main(int argc, char* const* argv)
{
parse_args(argc, argv);
if (command)
{
struct scope* scope = new_scope();
struct expression* expression = parse(command);
bool any_syntax_errors = foreach_syntax_error(expression,
print_syntax_error);
if (!any_syntax_errors)
{
struct value* value = evaluate(expression, scope);
print(value);
free_value(value);
}
free_expression(expression);
free_scope(scope);
}
else
{
struct scope* scope = new_scope();
for (char* line; (line = readline(">>> ")); free(line))
{
if (!*line) continue;
add_history(line);
struct expression* expression = parse(line);
struct value* value = evaluate(expression, scope);
print(value);
free_value(value);
free_expression(expression);
}
free_scope(scope);
}
return 0;
}