qc/main.c

3262 lines
72 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 CHECK assert(!"CHECK");
#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_va(const char* fmt, va_list va)
{
struct string* this = malloc(sizeof(*this));
int x = vasprintf(&this->data, fmt, va);
if (x < 0)
{
abort();
}
this->refcount = 1;
return this;
}
struct string* new_string_from_fmt(const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
struct string* this = new_string_from_fmt_va(fmt, ap);
va_end(ap);
return this;
}
struct string* inc_string(struct string* this)
{
if (this)
this->refcount++;
return this;
}
int compare_strings(const struct string* a, const struct string* b)
{
return strcmp(a->data, b->data);
}
int compare_strings_vv(const void* a, const void* b)
{
return compare_strings(
(const struct string*) a,
(const struct string*) b);
}
void free_string(struct string* this)
{
if (this && !--this->refcount)
{
free(this->data);
free(this);
}
}
void free_string_v(void* ptr)
{
free_string((struct string*) ptr);
}
struct stringset
{
struct avl_tree_t* tree;
unsigned refcount;
};
struct stringset* new_stringset(void)
{
struct stringset* this = malloc(sizeof(*this));
this->tree = avl_alloc_tree(compare_strings_vv, free_string_v);
this->refcount = 1;
return this;
}
bool stringset_add(struct stringset* this, struct string* new)
{
bool is_new;
struct avl_node_t* node = avl_insert(this->tree, new);
if (node)
{
inc_string(new);
is_new = true;
}
else
{
TODO;
}
return is_new;
}
bool stringset_update(struct stringset* this, const struct stringset* updateme)
{
bool is_new = false;
for (struct avl_node_t* i = updateme->tree->head; i; i = i->next)
{
struct avl_node_t* node = avl_insert(this->tree, i->item);
if (node)
{
inc_string(i->item);
is_new = true;
}
else if (errno == EEXIST)
{
;
}
else
{
TODO;
}
}
return is_new;
}
struct stringset* inc_stringset(struct stringset* this)
{
if (this)
this->refcount++;
return this;
}
void stringset_println(const struct stringset* this)
{
for (struct avl_node_t* i = this->tree->head; i; i = i->next)
{
const struct string* str = i->item;
printf("%s\n", str->data);
}
}
void free_stringset(struct stringset* this)
{
if (this && !--this->refcount)
{
avl_free_tree(this->tree);
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,
ek_integer_divide,
ek_remainder,
ek_exponent,
// bitwise operator:
ek_leftbitshift,
ek_rightbitshift,
// 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;
unsigned column;
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(
unsigned column,
struct string* error_message)
{
struct expression* this = malloc(sizeof(*this));
this->kind = ek_syntax_error;
this->column = column;
this->string = inc_string(error_message);
this->center = NULL;
this->left = NULL;
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* new_ternary_expression(
struct expression* center,
struct expression* left,
struct expression* right)
{
struct expression* this = malloc(sizeof(*this));
this->kind = ek_ternary;
this->string = NULL;
this->center = inc_expression(center);
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);
}
}
enum value_kind
{
vk_number,
vk_error,
};
struct value
{
enum value_kind kind;
struct stringset* errors;
mpq_t mpq;
unsigned refcount;
};
struct value* new_error_value(struct stringset* errors)
{
struct value* this = malloc(sizeof(*this));
this->kind = vk_error;
this->errors = inc_stringset(errors);
mpq_init(this->mpq);
this->refcount = 1;
return this;
}
struct value* new_error_value_from_fmt(const char* fmt, ...)
{
va_list va;
va_start(va, fmt);
struct string* message = new_string_from_fmt_va(fmt, va);
struct stringset* set = new_stringset();
stringset_add(set, message);
struct value* this = new_error_value(set);
free_stringset(set);
free_string(message);
va_end(va);
return this;
}
struct value* new_error_value_from_union(
const struct value* left,
const struct value* right)
{
assert(left->kind == vk_error);
assert(right->kind == vk_error);
struct stringset* set = new_stringset();
stringset_update(set, left->errors);
stringset_update(set, right->errors);
struct value* retval = new_error_value(set);
free_stringset(set);
return retval;
}
struct value* new_value_from_int(int x)
{
struct value* this = malloc(sizeof(*this));
this->kind = vk_number;
this->errors = NULL;
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));
this->kind = vk_number;
this->errors = NULL;
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_stringset(this->errors);
free(this);
}
}
struct value* scan(const char* text)
{
const char* moving = text;
const char* digits = "0123456789";
unsigned ibase = 10;
if (text[0] == '0' && text[1] == 'b')
{
digits = "01";
ibase = 2;
moving += 2;
}
else if (text[0] == '0' && text[1] == 'x')
{
digits = "0123456789ABCDEF";
ibase = 16;
moving += 2;
}
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, ibase, 1);
while ('_' == *moving || (*moving && index(digits, toupper(*moving))))
{
if ('_' == *moving)
{
moving++;
}
else
{
mpq_set_si(tmp, index(digits, toupper(*moving++)) - digits, 1);
mpq_mul(value, value, base);
mpq_add(value, value, tmp);
}
}
while ('_' == *moving)
{
moving++;
}
if (*moving == '.')
{
mpq_t factor; mpq_init(factor);
moving++;
mpq_set_si(factor, 1, ibase);
while ('_' == *moving || (*moving && index(digits, toupper(*moving))))
{
if ('_' == *moving)
{
moving++;
}
else
{
mpq_set_si(tmp, index(digits, toupper(*moving++)) - digits, 1);
mpq_mul(tmp, factor, tmp);
mpq_add(value, value, tmp);
mpq_div(factor, factor, base);
}
}
mpq_clear(factor);
}
while ('_' == *moving)
{
moving++;
}
assert(*moving == '\0');
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);
}
enum token
{
t_uninitialized,
t_error,
// primary:
t_identifier,
t_literal,
t_binary,
t_hexadecimal,
// brakets:
t_oparen,
t_cparen,
// arithmetic operators:
t_plus,
t_minus,
t_asterisk,
t_slash,
t_percent,
t_slash_slash,
t_asterisk_asterisk,
// comparision operators:
t_lessthan,
t_lessthan_equals,
t_lessthan_lessthan,
t_greaterthan,
t_greaterthan_equals,
t_greaterthan_greaterthan,
t_emark_equals,
t_equals_equals,
// logical operators:
t_vbar_vbar,
t_ampersand_ampersand,
// misc:
t_emark,
t_qmark,
t_colon,
t_equals,
t_comma,
t_EOF,
number_of_tokens,
};
static const char* const tokennames[number_of_tokens] = {
[t_EOF] = "EOF",
[t_identifier] = "identifier",
[t_literal] = "literal",
[t_binary] = "binary-literal",
[t_hexadecimal] = "hexadecimal-literal",
[t_oparen] = "open parentheses",
[t_cparen] = "close parentheses",
[t_plus] = "plus",
[t_minus] = "minus",
[t_asterisk] = "asterisk",
[t_asterisk_asterisk] = "double-asterisk",
[t_percent] = "percent",
[t_slash] = "slash",
[t_slash_slash] = "double-slash",
[t_lessthan] = "less-than",
[t_lessthan_equals] = "less-than-or-equal-to",
[t_greaterthan] = "greater-than",
[t_greaterthan_equals] = "greater-than-or-equal-to",
[t_emark_equals] = "not-equal-to",
[t_equals_equals] = "equal-to",
[t_vbar_vbar] = "logical-or",
[t_ampersand_ampersand] = "logical-and",
[t_emark] = "exclamation mark",
[t_qmark] = "question mark",
[t_colon] = "colon",
[t_equals] = "assignment",
[t_comma] = "comma",
};
struct tokenizer
{
const char* text;
unsigned start_index;
unsigned index;
enum token token;
struct buffer {
char* data;
size_t n, cap;
} buffer;
};
struct tokenizer* new_tokenizer(const char* text)
{
struct tokenizer* this = malloc(sizeof(*this));
this->text = text;
this->start_index = 0;
this->index = 0;
this->token = t_uninitialized;
this->buffer.data = NULL;
this->buffer.n = 0;
this->buffer.cap = 0;
return this;
}
void tokenizer_append_char(
struct tokenizer* this,
char code)
{
if (this->buffer.n == this->buffer.cap)
{
this->buffer.cap = this->buffer.cap << 1 ?: 1;
this->buffer.data = realloc(
this->buffer.data,
sizeof(*this->buffer.data) * this->buffer.cap);
}
this->buffer.data[this->buffer.n++] = code;
}
enum tokenizer_state {
ts_error,
ts_EOF,
ts_literal,
ts_identifier,
ts_equals,
ts_comma,
ts_slash,
ts_plus,
ts_minus,
ts_qmark,
ts_emark,
ts_colon,
ts_percent,
ts_asterisk,
ts_asterisk_asterisk,
ts_lessthan,
ts_lessthan_equals,
ts_lessthan_lessthan,
ts_greaterthan,
ts_greaterthan_equals,
ts_greaterthan_greaterthan,
ts_equals_equals,
ts_slash_slash,
ts_oparen,
ts_cparen,
ts_vbar_vbar,
ts_start,
ts_reading_literal_prefix,
ts_reading_literal,
ts_reading_literal2,
ts_reading_literal_binary,
ts_reading_literal_binary2,
ts_reading_literal_hexadecimal,
ts_reading_literal_hexadecimal2,
ts_reading_identifier,
ts_reading_equals,
ts_reading_equals_equals,
ts_reading_slash,
ts_reading_slash_slash,
ts_reading_comma,
ts_reading_plus,
ts_reading_minus,
ts_reading_qmark,
ts_reading_emark,
ts_reading_colon,
ts_reading_asterisk,
ts_reading_asterisk_asterisk,
ts_reading_percent,
ts_reading_lessthan,
ts_reading_lessthan_equals,
ts_reading_lessthan_lessthan,
ts_reading_greaterthan,
ts_reading_greaterthan_equals,
ts_reading_greaterthan_greaterthan,
ts_reading_oparen,
ts_reading_cparen,
ts_reading_vbar,
ts_reading_vbar_vbar,
number_of_tokenizer_states,
} tokenizer_lookup[number_of_tokenizer_states][128] = {
#define ANY 0 ... 127
// skip whitespace:
[ts_start][' '] = ts_start,
// EOF token:
[ts_start][0] = ts_EOF,
// binary: "0b" ['_', '0', '1']+ ('.' ['_', '0', '1']*)?
// hexadecimal: "0x" [_0-9a-fA-F]+ (.[_0-9a-fA-F]*)?
// literal: [0-9]+ [_0-9]* (. [_0-9]*)?
[ts_start]['0'] = ts_reading_literal_prefix,
[ts_reading_literal_prefix][ANY] = ts_literal,
[ts_reading_literal_prefix]['b'] = ts_reading_literal_binary,
[ts_reading_literal_binary][ ANY ] = ts_literal,
[ts_reading_literal_binary]['0' ... '1'] = ts_reading_literal_binary,
[ts_reading_literal_binary][ '_' ] = ts_reading_literal_binary,
[ts_reading_literal_binary][ '.' ] = ts_reading_literal_binary2,
[ts_reading_literal_binary2][ ANY ] = ts_literal,
[ts_reading_literal_binary2][ '_' ] = ts_reading_literal_binary2,
[ts_reading_literal_binary2]['0' ... '1'] = ts_reading_literal_binary2,
[ts_reading_literal_prefix]['x'] = ts_reading_literal_hexadecimal,
[ts_reading_literal_hexadecimal][ ANY ] = ts_literal,
[ts_reading_literal_hexadecimal]['0' ... '9'] = ts_reading_literal_hexadecimal,
[ts_reading_literal_hexadecimal]['a' ... 'f'] = ts_reading_literal_hexadecimal,
[ts_reading_literal_hexadecimal]['A' ... 'F'] = ts_reading_literal_hexadecimal,
[ts_reading_literal_hexadecimal][ '_' ] = ts_reading_literal_hexadecimal,
[ts_reading_literal_hexadecimal][ '.' ] = ts_reading_literal_hexadecimal2,
[ts_reading_literal_hexadecimal2][ ANY ] = ts_literal,
[ts_reading_literal_hexadecimal2][ '_' ] = ts_reading_literal_hexadecimal2,
[ts_reading_literal_hexadecimal2]['0' ... '9'] = ts_reading_literal_hexadecimal2,
[ts_reading_literal_hexadecimal2]['a' ... 'f'] = ts_reading_literal_hexadecimal2,
[ts_reading_literal_hexadecimal2]['A' ... 'F'] = ts_reading_literal_hexadecimal2,
[ts_reading_literal_prefix]['_'] = ts_reading_literal,
[ts_reading_literal_prefix]['.'] = ts_reading_literal2,
[ts_reading_literal_prefix]['0' ... '9'] = ts_reading_literal,
[ts_start]['1' ... '9'] = ts_reading_literal,
[ts_reading_literal][ ANY ] = ts_literal,
[ts_reading_literal][ '_' ] = ts_reading_literal,
[ts_reading_literal]['0' ... '9'] = ts_reading_literal,
[ts_reading_literal]['a' ... 'z'] = ts_error,
[ts_reading_literal][ '.' ] = ts_reading_literal2,
[ts_reading_literal2][ ANY ] = ts_literal,
[ts_reading_literal2][ '_' ] = ts_reading_literal2,
[ts_reading_literal2]['0' ... '9'] = ts_reading_literal2,
// identifiers:
[ts_start][ '_' ] = ts_reading_identifier,
[ts_start]['a' ... 'z'] = ts_reading_identifier,
[ts_reading_identifier][ ANY ] = ts_identifier,
[ts_reading_identifier][ '_' ] = ts_reading_identifier,
[ts_reading_identifier]['0' ... '9'] = ts_reading_identifier,
[ts_reading_identifier]['a' ... 'z'] = ts_reading_identifier,
// symbols:
[ts_start]['+'] = ts_reading_plus, [ts_reading_plus][ANY] = ts_plus,
[ts_start]['-'] = ts_reading_minus, [ts_reading_minus][ANY] = ts_minus,
[ts_start]['%'] = ts_reading_percent, [ts_reading_percent][ANY] = ts_percent,
[ts_start]['?'] = ts_reading_qmark, [ts_reading_qmark][ANY] = ts_qmark,
[ts_start]['!'] = ts_reading_emark, [ts_reading_emark][ANY] = ts_emark,
[ts_start][':'] = ts_reading_colon, [ts_reading_colon][ANY] = ts_colon,
[ts_start][','] = ts_reading_comma, [ts_reading_comma][ANY] = ts_comma,
[ts_start]['('] = ts_reading_oparen, [ts_reading_oparen][ANY] = ts_oparen,
[ts_start][')'] = ts_reading_cparen, [ts_reading_cparen][ANY] = ts_cparen,
// '*' or '**'
[ts_start]['*'] = ts_reading_asterisk,
[ts_reading_asterisk][ANY] = ts_asterisk,
[ts_reading_asterisk]['*'] = ts_reading_asterisk_asterisk,
[ts_reading_asterisk_asterisk][ANY] = ts_asterisk_asterisk,
// '/' or '//':
[ts_start]['/'] = ts_reading_slash,
[ts_reading_slash][ANY] = ts_slash,
[ts_reading_slash]['/'] = ts_reading_slash_slash,
[ts_reading_slash_slash][ANY] = ts_slash_slash,
// '=' or '==':
[ts_start]['='] = ts_reading_equals,
[ts_reading_equals][ANY] = ts_equals,
[ts_reading_equals]['='] = ts_reading_equals_equals,
[ts_reading_equals_equals][ANY] = ts_equals_equals,
// '<' or '<=' or '<<':
[ts_start]['<'] = ts_reading_lessthan,
[ts_reading_lessthan][ANY] = ts_lessthan,
[ts_reading_lessthan]['='] = ts_reading_lessthan_equals,
[ts_reading_lessthan_equals][ANY] = ts_lessthan_equals,
[ts_reading_lessthan]['<'] = ts_reading_lessthan_lessthan,
[ts_reading_lessthan_lessthan][ANY] = ts_lessthan_lessthan,
// '>' or '>=' or '>>':
[ts_start]['>'] = ts_reading_greaterthan,
[ts_reading_greaterthan][ANY] = ts_greaterthan,
[ts_reading_greaterthan]['='] = ts_reading_greaterthan_equals,
[ts_reading_greaterthan_equals][ANY] = ts_greaterthan_equals,
[ts_reading_greaterthan]['>'] = ts_reading_greaterthan_greaterthan,
[ts_reading_greaterthan_greaterthan][ANY] = ts_greaterthan_greaterthan,
// '||':
[ts_start]['|'] = ts_reading_vbar,
[ts_reading_vbar]['|'] = ts_reading_vbar_vbar,
[ts_reading_vbar_vbar][ANY] = ts_vbar_vbar,
};
void tokenizer_next(
struct tokenizer* this)
{
this->buffer.n = 0;
this->start_index = this->index;
enum tokenizer_state state = ts_start;
while (state >= ts_start)
{
assert(this->text[this->index] >= 0);
state = tokenizer_lookup[state][(uint8_t) this->text[this->index]];
if (state > ts_start)
{
tokenizer_append_char(this, this->text[this->index]);
this->index++;
}
if (state == ts_start)
{
this->buffer.n = 0;
this->index++;
this->start_index = this->index;
}
}
// for sake of the error message:
if (state == ts_error)
{
tokenizer_append_char(this, this->text[this->index]);
}
tokenizer_append_char(this, '\0');
switch (state)
{
case ts_error:
{
this->token = t_error;
break;
}
case ts_EOF:
{
this->token = t_EOF;
break;
}
case ts_literal:
{
this->token = t_literal;
break;
}
case ts_identifier:
{
this->token = t_identifier;
break;
}
case ts_equals:
{
this->token = t_equals;
break;
}
case ts_comma:
{
this->token = t_comma;
break;
}
case ts_plus:
{
this->token = t_plus;
break;
}
case ts_qmark:
{
this->token = t_qmark;
break;
}
case ts_minus:
{
this->token = t_minus;
break;
}
case ts_slash:
{
this->token = t_slash;
break;
}
case ts_equals_equals:
{
this->token = t_equals_equals;
break;
}
case ts_emark:
{
this->token = t_emark;
break;
}
case ts_oparen:
{
this->token = t_oparen;
break;
}
case ts_cparen:
{
this->token = t_cparen;
break;
}
case ts_percent:
{
this->token = t_percent;
break;
}
case ts_lessthan:
{
this->token = t_lessthan;
break;
}
case ts_lessthan_equals:
{
this->token = t_lessthan_equals;
break;
}
case ts_colon:
{
this->token = t_colon;
break;
}
case ts_asterisk:
{
this->token = t_asterisk;
break;
}
case ts_vbar_vbar:
{
this->token = t_vbar_vbar;
break;
}
case ts_slash_slash:
{
this->token = t_slash_slash;
break;
}
case ts_lessthan_lessthan:
{
this->token = t_lessthan_lessthan;
break;
}
case ts_greaterthan_greaterthan:
{
this->token = t_greaterthan_greaterthan;
break;
}
case ts_asterisk_asterisk:
{
this->token = t_asterisk_asterisk;
break;
}
default:
TODO;
break;
}
}
void free_tokenizer(
struct tokenizer* this)
{
free(this->buffer.data);
free(this);
}
struct string* make_unexpected_token_message(
struct tokenizer* tokenizer)
{
if (tokenizer->token == t_error)
{
return new_string_from_fmt(
"unexpected unknown token '%s'",
tokenizer->buffer.data);
}
else
{
assert(tokennames[tokenizer->token]);
return new_string_from_fmt(
"unexpected %s token",
tokennames[tokenizer->token]);
}
}
struct expression* parse_root(struct tokenizer* tokenizer);
struct expression* parse_primary(struct tokenizer* tokenizer)
{
struct expression* retval = NULL;
switch (tokenizer->token)
{
case t_error:
{
struct string* message = new_string_from_fmt(
"unknown token '%s'", tokenizer->buffer.data);
retval = new_syntax_error_expression(
/* column: */ tokenizer->start_index + 1,
/* message: */ message);
tokenizer_next(tokenizer);
free_string(message);
break;
}
case t_literal:
{
struct value* value = scan(tokenizer->buffer.data);
retval = new_literal_expression(value);
tokenizer_next(tokenizer);
free_value(value);
break;
}
case t_hexadecimal:
{
TODO;
break;
}
case t_identifier:
{
struct string* name = new_string(tokenizer->buffer.data);
retval = new_variable_expression(name);
tokenizer_next(tokenizer);
free_string(name);
break;
}
case t_oparen:
{
tokenizer_next(tokenizer);
struct expression* sub = parse_root(tokenizer);
if (sub->kind == ek_syntax_error)
{
retval = inc_expression(sub);
}
else if (tokenizer->token == t_cparen)
{
tokenizer_next(tokenizer);
retval = inc_expression(sub);
}
else
{
TODO;
}
free_expression(sub);
break;
}
default:
{
struct string* message = make_unexpected_token_message(tokenizer);
retval = new_syntax_error_expression(
/* column: */ tokenizer->start_index + 1,
/* message: */ message);
tokenizer_next(tokenizer);
free_string(message);
break;
}
}
assert(retval);
return retval;
}
struct expression* parse_prefix(struct tokenizer* tokenizer)
{
struct expression* retval = NULL;
switch (tokenizer->token)
{
case t_emark:
{
tokenizer_next(tokenizer);
struct expression* sub = parse_prefix(tokenizer);
if (sub->kind == ek_syntax_error)
{
retval = sub;
}
else
{
TODO;
#if 0
struct expression* retval =
new_logical_not_expression(sub);
free_expression(sub);
return retval;
#endif
}
break;
}
case t_plus:
{
tokenizer_next(tokenizer);
struct expression* sub = parse_prefix(tokenizer);
if (sub->kind == ek_syntax_error)
{
retval = sub;
}
else
{
TODO;
#if 0
retval = new_positive_expression(sub);
free_expression(sub);
#endif
}
break;
}
case t_minus:
{
tokenizer_next(tokenizer);
struct expression* sub = parse_prefix(tokenizer);
if (sub->kind == ek_syntax_error)
{
retval = inc_expression(sub);
}
else
{
retval = new_negative_expression(sub);
}
free_expression(sub);
break;
}
default:
{
retval = parse_primary(tokenizer);
break;
}
}
assert(retval);
return retval;
}
struct expression* parse_exponent(struct tokenizer* tokenizer)
{
struct expression* left = parse_prefix(tokenizer);
while (true
&& left->kind != ek_syntax_error
&& (tokenizer->token == t_asterisk_asterisk))
{
tokenizer_next(tokenizer);
struct expression* right = parse_prefix(tokenizer);
if (right->kind == ek_syntax_error)
{
free_expression(left);
left = inc_expression(right);
}
else
{
struct expression* retval =
new_binary_expression(ek_exponent, left, right);
left = retval;
}
free_expression(right);
}
return left;
}
struct expression* parse_multiplicative(struct tokenizer* tokenizer)
{
struct expression* left = parse_exponent(tokenizer);
while (true
&& left->kind != ek_syntax_error
&& (false
|| tokenizer->token == t_asterisk
|| tokenizer->token == t_slash
|| tokenizer->token == t_slash_slash
|| tokenizer->token == t_percent))
{
switch (tokenizer->token)
{
case t_asterisk:
{
tokenizer_next(tokenizer);
struct expression* right = parse_exponent(tokenizer);
if (right->kind == ek_syntax_error)
{
free_expression(left);
left = inc_expression(right);
}
else
{
struct expression* retval =
new_binary_expression(ek_multiply, left, right);
left = retval;
}
free_expression(right);
break;
}
case t_slash:
{
tokenizer_next(tokenizer);
struct expression* right = parse_exponent(tokenizer);
if (right->kind == ek_syntax_error)
{
free_expression(left);
left = inc_expression(right);
}
else
{
struct expression* retval =
new_binary_expression(ek_divide, left, right);
free_expression(left);
left = retval;
}
free_expression(right);
break;
}
case t_slash_slash:
{
tokenizer_next(tokenizer);
struct expression* right = parse_exponent(tokenizer);
if (right->kind == ek_syntax_error)
{
free_expression(left);
left = inc_expression(right);
}
else
{
struct expression* retval =
new_binary_expression(ek_integer_divide, left, right);
free_expression(left);
left = retval;
}
free_expression(right);
break;
}
case t_percent:
{
tokenizer_next(tokenizer);
struct expression* right = parse_exponent(tokenizer);
if (right->kind == ek_syntax_error)
{
free_expression(left);
left = inc_expression(right);
}
else
{
struct expression* retval =
new_binary_expression(ek_remainder, left, right);
free_expression(left);
left = retval;
}
free_expression(right);
break;
}
default:
break;
}
}
return left;
}
struct expression* parse_additive(struct tokenizer* tokenizer)
{
struct expression* left = parse_multiplicative(tokenizer);
while (true
&& left->kind != ek_syntax_error
&& (false
|| tokenizer->token == t_plus
|| tokenizer->token == t_minus))
{
switch (tokenizer->token)
{
case t_plus:
{
tokenizer_next(tokenizer);
struct expression* right = parse_multiplicative(tokenizer);
if (right->kind == ek_syntax_error)
{
free_expression(left);
left = right;
}
else
{
struct expression* retval =
new_binary_expression(ek_add, left, right);
free_expression(left);
free_expression(right);
left = retval;
}
break;
}
case t_minus:
{
tokenizer_next(tokenizer);
struct expression* right = parse_multiplicative(tokenizer);
if (right->kind == ek_syntax_error)
{
TODO;
}
else
{
struct expression* retval =
new_binary_expression(ek_subtract, left, right);
free_expression(left);
left = retval;
}
free_expression(right);
break;
}
default:
TODO;
break;
}
}
return left;
}
struct expression* parse_shift(struct tokenizer* tokenizer)
{
struct expression* left = parse_additive(tokenizer);
while (true
&& left->kind != ek_syntax_error
&& (false
|| tokenizer->token == t_lessthan_lessthan
|| tokenizer->token == t_greaterthan_greaterthan))
{
switch (tokenizer->token)
{
case t_lessthan_lessthan:
{
tokenizer_next(tokenizer);
struct expression* right = parse_additive(tokenizer);
if (right->kind == ek_syntax_error)
{
free_expression(left);
left = right;
}
else
{
struct expression* retval =
new_binary_expression(ek_leftbitshift, left, right);
free_expression(left);
free_expression(right);
left = retval;
}
break;
}
case t_greaterthan_greaterthan:
{
tokenizer_next(tokenizer);
struct expression* right = parse_additive(tokenizer);
if (right->kind == ek_syntax_error)
{
TODO;
}
else
{
struct expression* retval =
new_binary_expression(ek_rightbitshift, left, right);
free_expression(left);
left = retval;
}
free_expression(right);
break;
}
default:
TODO;
break;
}
}
return left;
}
struct expression* parse_comparision(struct tokenizer* tokenizer)
{
struct expression* left = parse_shift(tokenizer);
while (true
&& left->kind != ek_syntax_error
&& (false
|| tokenizer->token == t_lessthan
|| tokenizer->token == t_lessthan_equals
|| tokenizer->token == t_greaterthan
|| tokenizer->token == t_greaterthan_equals))
{
switch (tokenizer->token)
{
case t_lessthan:
{
tokenizer_next(tokenizer);
struct expression* right = parse_shift(tokenizer);
if (right->kind == ek_syntax_error)
{
free_expression(left);
left = inc_expression(right);
}
else
{
struct expression* retval =
new_binary_expression(ek_less_than, left, right);
free_expression(left);
left = retval;
}
free_expression(right);
break;
}
case t_lessthan_equals:
{
tokenizer_next(tokenizer);
struct expression* right = parse_additive(tokenizer);
if (right->kind == ek_syntax_error)
{
free_expression(left);
left = inc_expression(right);
}
else
{
struct expression* retval =
new_binary_expression(ek_less_than_equal_to, left, right);
free_expression(left);
left = retval;
}
free_expression(right);
break;
}
case t_greaterthan:
{
TODO;
#if 0
next_token();
struct expression* right =
parse_additive();
struct expression* retval =
new_binary_expression(ek_greater_than, left, right);
free_expression(left);
free_expression(right);
left = retval;
goto again;
#endif
}
case t_greaterthan_equals:
{
TODO;
#if 0
next_token();
struct expression* right =
parse_additive();
struct expression* retval =
new_binary_expression(ek_greater_than_equal_to, left, right);
free_expression(left);
free_expression(right);
left = retval;
goto again;
#endif
}
default:
break;
}
}
return left;
}
struct expression* parse_equality(struct tokenizer* tokenizer)
{
struct expression* left = parse_comparision(tokenizer);
while (true
&& left->kind != ek_syntax_error
&& (false
|| tokenizer->token == t_equals_equals
|| tokenizer->token == t_emark_equals))
{
switch (tokenizer->token)
{
case t_equals_equals:
{
tokenizer_next(tokenizer);
struct expression* right = parse_comparision(tokenizer);
if (right->kind == ek_syntax_error)
{
free_expression(left);
left = inc_expression(right);
}
else
{
struct expression* retval =
new_binary_expression(ek_equal_to, left, right);
free_expression(left);
left = retval;
}
free_expression(right);
break;
}
case t_emark_equals:
{
TODO;
#if 0
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;
#endif
}
default:
break;
}
}
return left;
}
struct expression* parse_logical_and(struct tokenizer* tokenizer)
{
struct expression* left = parse_equality(tokenizer);
while (tokenizer->token == t_ampersand_ampersand)
{
TODO;
}
return left;
}
struct expression* parse_logical_or(struct tokenizer* tokenizer)
{
struct expression* left = parse_logical_and(tokenizer);
while (tokenizer->token == t_vbar_vbar)
{
tokenizer_next(tokenizer);
struct expression* right = parse_comparision(tokenizer);
struct expression* retval =
new_binary_expression(ek_logical_or, left, right);
free_expression(left);
free_expression(right);
left = retval;
}
return left;
}
struct expression* parse_ternary(struct tokenizer* tokenizer)
{
struct expression* center = parse_logical_or(tokenizer);
while (true
&& center->kind != ek_syntax_error
&& tokenizer->token == t_qmark)
{
tokenizer_next(tokenizer);
struct expression* left = parse_root(tokenizer);
if (left->kind == ek_syntax_error)
{
free_expression(center);
center = inc_expression(left);
}
else if (tokenizer->token == t_colon)
{
tokenizer_next(tokenizer);
struct expression* right = parse_logical_or(tokenizer);
if (right->kind == ek_syntax_error)
{
free_expression(center);
center = inc_expression(right);
}
else
{
struct expression* new = new_ternary_expression(center, left, right);
free_expression(center);
center = new;
}
free_expression(right);
}
else
{
struct string* message = make_unexpected_token_message(tokenizer);
struct expression* error = new_syntax_error_expression(
tokenizer->start_index + 1, message);
free_expression(center);
center = error;
tokenizer_next(tokenizer);
free_string(message);
}
free_expression(left);
}
return center;
}
struct expression* parse_assign(struct tokenizer* tokenizer)
{
struct expression* left = parse_ternary(tokenizer);
if (tokenizer->token == t_equals)
{
tokenizer_next(tokenizer);
struct expression* right = parse_assign(tokenizer);
struct expression* retval = new_binary_expression(ek_assign, left, right);
free_expression(left);
free_expression(right);
return retval;
}
return left;
}
struct expression* parse_comma(struct tokenizer* tokenizer)
{
struct expression* left = parse_assign(tokenizer);
while (tokenizer->token == t_comma)
{
tokenizer_next(tokenizer);
struct expression* right = parse_assign(tokenizer);
struct expression* retval = new_binary_expression(ek_comma, left, right);
free_expression(left);
free_expression(right);
left = retval;
}
return left;
}
struct expression* parse_root(struct tokenizer* tokenizer)
{
return parse_comma(tokenizer);
}
struct expression* parse(const char* text)
{
struct tokenizer* tokenizer = new_tokenizer(text);
tokenizer_next(tokenizer);
struct expression* root = parse_root(tokenizer);
if (root->kind != ek_syntax_error && tokenizer->token != t_EOF)
{
struct string* message = make_unexpected_token_message(tokenizer);
struct expression* error = new_syntax_error_expression(
tokenizer->start_index + 1, message);
free_expression(root);
root = error;
free_string(message);
}
free_tokenizer(tokenizer);
return root;
}
#if 0
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_remainder: TODO; break;
case ek_assign:
{
TODO;
break;
};
case ek_comma:
{
TODO;
break;
};
}
return NULL;
}
#endif
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_error_value_from_fmt(
"error: use of undefined variable '%s'!",
expression->string->data);
}
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);
if (left->kind == vk_error && right->kind == vk_error)
{
TODO;
// new_error_value_from_unionnew_error_value_from_union
struct stringset* set = new_stringset();
stringset_update(set, left->errors);
stringset_update(set, right->errors);
retval = new_error_value(set);
free_stringset(set);
}
else if (left->kind == vk_error)
{
TODO;
}
else if (right->kind == vk_error)
{
TODO;
}
else
{
mpq_t q;
mpq_init(q);
mpq_add(q, left->mpq, right->mpq);
retval = new_value(q);
mpq_clear(q);
}
free_value(left), free_value(right);
break;
}
case ek_subtract:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
if (left->kind == vk_error && right->kind == vk_error)
{
TODO
// new_error_value_from_union
struct stringset* set = new_stringset();
stringset_update(set, left->errors);
stringset_update(set, right->errors);
retval = new_error_value(set);
free_stringset(set);
}
else if (left->kind == vk_error)
{
TODO;
}
else if (right->kind == vk_error)
{
TODO;
}
else
{
TODO;
#if 0
mpq_t q;
mpq_init(q);
mpq_sub(q, left->mpq, right->mpq);
retval = new_value(q);
mpq_clear(q);
#endif
}
free_value(left);
free_value(right);
break;
}
case ek_multiply:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
if (left->kind == vk_error && right->kind == vk_error)
{
TODO;
// new_error_value_from_union
struct stringset* set = new_stringset();
stringset_update(set, left->errors);
stringset_update(set, right->errors);
retval = new_error_value(set);
free_stringset(set);
}
else if (left->kind == vk_error)
{
retval = inc_value(left);
}
else if (right->kind == vk_error)
{
retval = inc_value(right);
}
else
{
TODO;
#if 0
mpq_t q;
mpq_init(q);
mpq_mul(q, left->mpq, right->mpq);
retval = new_value(q);
mpq_clear(q);
#endif
}
free_value(left), free_value(right);
break;
}
case ek_integer_divide:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
if (left->kind == vk_error && right->kind == vk_error)
{
TODO;
// new_error_value_from_union
struct stringset* set = new_stringset();
stringset_update(set, left->errors);
stringset_update(set, right->errors);
retval = new_error_value(set);
free_stringset(set);
}
else if (left->kind == vk_error)
{
retval = inc_value(left);
}
else if (right->kind == vk_error)
{
retval = inc_value(right);
}
else
{
mpq_t q;
mpq_init(q);
mpq_div(q, left->mpq, right->mpq);
mpz_tdiv_q(mpq_numref(q), mpq_numref(q), mpq_denref(q));
mpz_set_si(mpq_denref(q), 1);
retval = new_value(q);
mpq_clear(q);
}
free_value(left), free_value(right);
break;
}
case ek_rightbitshift:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
if (left->kind == vk_error && right->kind == vk_error)
{
retval = new_error_value_from_union(left, right);
}
else if (left->kind == vk_error)
{
retval = inc_value(left);
}
else if (right->kind == vk_error)
{
retval = inc_value(right);
}
else if (mpz_cmp_si(mpq_denref(right->mpq), 1) == 0)
{
if (mpq_sgn(right->mpq) > 0)
{
if (mpz_fits_ulong_p(mpq_numref(right->mpq)))
{
unsigned long r = mpz_get_ui(mpq_numref(right->mpq));
mpq_t q;
mpq_init(q);
mpq_div_2exp(q, left->mpq, r);
retval = new_value(q);
mpq_clear(q);
}
else
{
retval = new_error_value_from_fmt(
"error: cannot right bitshift beyond ULONG_MAX");
}
}
else
{
retval = new_error_value_from_fmt(
"error: cannot right bitshift by a negative value");
}
}
else
{
retval = new_error_value_from_fmt(
"error: cannot right bitshift by a fractional value");
}
free_value(left), free_value(right);
break;
}
case ek_leftbitshift:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
if (left->kind == vk_error && right->kind == vk_error)
{
retval = new_error_value_from_union(left, right);
}
else if (left->kind == vk_error)
{
retval = inc_value(left);
}
else if (right->kind == vk_error)
{
retval = inc_value(right);
}
else if (mpz_cmp_si(mpq_denref(right->mpq), 1) == 0)
{
if (mpq_sgn(right->mpq) > 0)
{
if (mpz_fits_ulong_p(mpq_numref(right->mpq)))
{
unsigned long rshift = mpz_get_ui(mpq_numref(right->mpq));
mpq_t q;
mpq_init(q);
mpq_mul_2exp(q, left->mpq, rshift);
retval = new_value(q);
mpq_clear(q);
}
else
{
retval = new_error_value_from_fmt(
"error: cannot left bitshift beyond ULONG_MAX");
}
}
else
{
retval = new_error_value_from_fmt(
"error: cannot left bitshift by a negative value");
}
}
else
{
retval = new_error_value_from_fmt(
"error: cannot left bitshift by fractional value");
}
free_value(left), free_value(right);
break;
}
case ek_exponent:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
if (left->kind == vk_error && right->kind == vk_error)
{
retval = new_error_value_from_union(left, right);
}
else if (left->kind == vk_error)
{
retval = inc_value(left);
}
else if (right->kind == vk_error)
{
retval = inc_value(right);
}
else if (mpz_cmp_si(mpq_denref(right->mpq), 1) == 0)
{
if (mpq_sgn(right->mpq) > 0)
{
if (mpz_fits_ulong_p(mpq_numref(right->mpq)))
{
unsigned long rpow = mpz_get_ui(mpq_numref(right->mpq));
mpz_t n, d;
mpz_init(n), mpz_init(d);
mpz_pow_ui(n, mpq_numref(left->mpq), rpow);
mpz_pow_ui(d, mpq_denref(left->mpq), rpow);
mpq_t q, t;
mpq_init(q), mpq_init(t);
mpq_set_z(q, n);
mpq_set_z(t, d);
mpq_div(q, q, t);
retval = new_value(q);
mpq_clear(q), mpq_clear(t);
}
else
{
retval = new_error_value_from_fmt(
"error: cannot exponentiate beyond ULONG_MAX");
}
}
else
{
retval = new_error_value_from_fmt(
"error: negative exponents not supported");
}
}
else
{
retval = new_error_value_from_fmt(
"error: cannot exponentiate by a fraction");
}
free_value(left), free_value(right);
break;
}
case ek_divide:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
if (left->kind == vk_error && right->kind == vk_error)
{
TODO;
// new_error_value_from_union
struct stringset* set = new_stringset();
stringset_update(set, left->errors);
stringset_update(set, right->errors);
retval = new_error_value(set);
free_stringset(set);
}
else if (left->kind == vk_error)
{
retval = inc_value(left);
}
else if (right->kind == vk_error)
{
retval = inc_value(right);
}
else
{
TODO;
#if 0
mpq_t q;
mpq_init(q);
mpq_div(q, left->mpq, right->mpq);
retval = new_value(q);
mpq_clear(q);
#endif
}
free_value(left), free_value(right);
break;
}
case ek_remainder:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
if (left->kind == vk_error && right->kind == vk_error)
{
TODO;
// new_error_value_from_union
struct stringset* set = new_stringset();
stringset_update(set, left->errors);
stringset_update(set, right->errors);
retval = new_error_value(set);
free_stringset(set);
}
else if (left->kind == vk_error)
{
retval = inc_value(left);
}
else if (right->kind == vk_error)
{
retval = inc_value(right);
}
else
{
mpq_t q;
mpq_init(q);
// (x % y) => x - (x // y) * y
mpq_div(q, left->mpq, right->mpq);
mpz_tdiv_q(mpq_numref(q), mpq_numref(q), mpq_denref(q));
mpz_set_si(mpq_denref(q), 1);
mpq_mul(q, q, right->mpq);
mpq_sub(q, left->mpq, q);
retval = new_value(q);
mpq_clear(q);
}
free_value(left), free_value(right);
break;
}
case ek_positive:
{
retval = evaluate(expression->center, scope);
break;
}
case ek_negative:
{
struct value* sub = evaluate(expression->center, scope);
if (sub->kind == vk_error)
{
TODO;
}
else
{
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:
{
TODO;
#if 0
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);
#endif
break;
}
case ek_greater_than_equal_to:
{
TODO;
#if 0
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;
#endif
}
case ek_less_than:
{
struct value* left = evaluate(expression->left, scope);
struct value* right = evaluate(expression->right, scope);
if (left->kind == vk_error && right->kind == vk_error)
{
TODO;
// new_error_value_from_union
struct stringset* set = new_stringset();
stringset_update(set, left->errors);
stringset_update(set, right->errors);
retval = new_error_value(set);
free_stringset(set);
}
else if (left->kind == vk_error)
{
TODO;
}
else if (right->kind == vk_error)
{
TODO;
}
else
{
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);
if (left->kind == vk_error && right->kind == vk_error)
{
TODO;
// new_error_value_from_union
struct stringset* set = new_stringset();
stringset_update(set, left->errors);
stringset_update(set, right->errors);
retval = new_error_value(set);
free_stringset(set);
}
else if (left->kind == vk_error)
{
TODO;
}
else if (right->kind == vk_error)
{
TODO;
}
else
{
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);
if (left->kind == vk_error && right->kind == vk_error)
{
TODO;
// new_error_value_from_union
struct stringset* set = new_stringset();
stringset_update(set, left->errors);
stringset_update(set, right->errors);
retval = new_error_value(set);
free_stringset(set);
}
else if (left->kind == vk_error)
{
TODO;
}
else if (right->kind == vk_error)
{
TODO;
}
else
{
retval = new_value_from_int(mpq_cmp(left->mpq, right->mpq) == 0);
}
free_value(left), free_value(right);
break;
}
case ek_not_equal_to:
{
TODO;
#if 0
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;
#endif
}
case ek_logical_not:
{
TODO;
#if 0
struct value* sub = evaluate(expression->center, scope);
retval = new_value_from_int(mpq_sgn(sub->mpq) == 0);
free_value(sub);
break;
#endif
}
case ek_logical_and:
{
TODO;
#if 0
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;
#endif
}
case ek_logical_or:
{
struct value* left = evaluate(expression->left, scope);
if (left->kind == vk_error)
{
struct value* right = evaluate(expression->right, scope);
if (right->kind == vk_error)
{
TODO;
// new_error_value_from_union
struct stringset* set = new_stringset();
stringset_update(set, left->errors);
stringset_update(set, right->errors);
retval = new_error_value(set);
free_stringset(set);
}
else
{
retval = inc_value(left);
}
free_value(right);
}
else
{
TODO;
#if 0
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;
#endif
}
free_value(left);
break;
}
case ek_ternary:
{
struct value* conditional = evaluate(expression->center, scope);
if (conditional->kind == vk_error)
{
retval = inc_value(conditional);
}
else if (mpq_sgn(conditional->mpq) != 0)
{
retval = evaluate(expression->left, scope);
}
else
{
retval = evaluate(expression->right, scope);
}
free_value(conditional);
break;
}
case ek_assign:
{
if (expression->left->kind == ek_variable)
{
struct value** lvalue = scope_lookup(
scope, expression->left->string);
retval = evaluate(expression->right, scope);
free_value(*lvalue), *lvalue = inc_value(retval);
}
else
{
TODO;
struct string* message = new_string_from_fmt(
"error: cannot assign to rvalue-expressions");
struct stringset* set = new_stringset();
stringset_add(set, message);
retval = new_error_value(set);
free_stringset(set);
free_string(message);
}
break;
};
case ek_comma:
{
TODO;
#if 0
free_value(evaluate(expression->left, scope));
retval = evaluate(expression->right, scope);
break;
#endif
};
}
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 = (unsigned int) 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)
{
switch (this->kind)
{
case vk_error:
{
stringset_println(this->errors);
break;
}
case vk_number:
{
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("");
break;
}
}
}
void syntax_error_print(
const struct expression* this)
{
assert(this->kind == ek_syntax_error);
printf("%*s↑\n", this->column - 1, "");
printf("%*s└ %s\n", this->column - 1, "", this->string->data);
}
int main(int argc, char* const* argv)
{
int retval = 0;
parse_args(argc, argv);
if (command)
{
struct scope* scope = new_scope();
struct expression* expression = parse(command);
if (expression->kind == ek_syntax_error)
{
printf("syntax error!\n");
printf("%s\n", command);
syntax_error_print(expression);
retval = 1;
}
else
{
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);
if (expression->kind == ek_syntax_error)
{
printf("syntax error!\n");
printf("%s\n", line);
syntax_error_print(expression);
retval = 1;
}
else
{
struct value* value = evaluate(expression, scope);
print(value);
free_value(value);
}
free_expression(expression);
}
free_scope(scope);
}
return retval;
}