libabacus/src/interactive.c

136 lines
4.3 KiB
C
Raw Normal View History

2018-05-23 15:41:17 -07:00
#include "libabacus.h"
2018-05-26 20:43:36 -07:00
#include "util.h"
2018-05-26 21:55:30 -07:00
#include "value.h"
#include <stdio.h>
2018-05-23 15:41:17 -07:00
2018-05-26 21:55:30 -07:00
#define TRY(expression) \
if (result == LIBAB_SUCCESS) \
result = expression;
2018-05-23 15:41:17 -07:00
#define INTERACTIONS 5
void* impl_parse(const char* string) {
double* data = malloc(sizeof(*data));
2018-05-26 21:55:30 -07:00
if (data) {
2018-05-23 15:41:17 -07:00
*data = strtod(string, NULL);
}
return data;
}
2018-05-26 21:55:30 -07:00
void impl_free(void* data) { free(data); }
2018-05-23 15:41:17 -07:00
libab_result function_atan(libab* ab, libab_ref_vec* params, libab_ref* into) {
2018-05-23 15:41:17 -07:00
printf("atan called\n");
libab_ref_null(into);
return LIBAB_SUCCESS;
}
libab_result function_atan2(libab* ab, libab_ref_vec* params, libab_ref* into) {
2018-05-23 15:41:17 -07:00
printf("atan2 called\n");
libab_ref_null(into);
return LIBAB_SUCCESS;
}
libab_result function_print_num(libab* ab, libab_ref_vec* params, libab_ref* into) {
double* param = libab_unwrap_param(params, 0);
printf("%f\n", *param);
libab_ref_null(into);
return LIBAB_SUCCESS;
}
libab_result create_double_value(libab* ab, double val, libab_ref* into) {
libab_ref type_num;
libab_result result = LIBAB_SUCCESS;
libab_get_type_num(ab, &type_num);
double* new_double = malloc(sizeof(*new_double));
if(new_double) {
*new_double = val;
result = libab_create_value_raw(into, new_double, &type_num);
if(result != LIBAB_SUCCESS) {
free(new_double);
}
} else {
result = LIBAB_MALLOC;
libab_ref_null(into);
}
libab_ref_free(&type_num);
return result;
}
#define OP_FUNCTION(name, expression) \
libab_result name(libab* ab, libab_ref_vec* params, libab_ref* into) { \
libab_result result = LIBAB_SUCCESS; \
double right; \
double left; \
printf(#name " called\n"); \
left = *((double*)libab_unwrap_param(params, 0)); \
right = *((double*)libab_unwrap_param(params, 1)); \
create_double_value(ab, expression, into); \
return result;\
}
2018-05-26 20:43:36 -07:00
OP_FUNCTION(function_plus, left + right)
OP_FUNCTION(function_minus, left - right)
OP_FUNCTION(function_times, left * right)
OP_FUNCTION(function_divide, left / right)
2018-05-23 15:41:17 -07:00
libab_result register_functions(libab* ab) {
libab_result result = LIBAB_SUCCESS;
libab_ref trig_type;
libab_ref atan2_type;
libab_ref difficult_type;
result = libab_create_type(ab, &trig_type, "(num)->num");
TRY(libab_create_type(ab, &atan2_type, "(num, num)->num"));
TRY(libab_create_type(ab, &difficult_type, "((num)->num)->num"));
TRY(libab_register_function(ab, "atan", &trig_type, function_atan));
TRY(libab_register_function(ab, "atan2", &atan2_type, function_atan2));
TRY(libab_register_function(ab, "plus", &atan2_type, function_plus));
TRY(libab_register_function(ab, "minus", &atan2_type, function_minus));
TRY(libab_register_function(ab, "times", &atan2_type, function_times));
TRY(libab_register_function(ab, "divide", &atan2_type, function_divide));
TRY(libab_register_function(ab, "print", &trig_type, function_print_num));
TRY(libab_register_operator_infix(ab, "+", 0, -1, "plus"));
TRY(libab_register_operator_infix(ab, "-", 0, -1, "minus"));
TRY(libab_register_operator_infix(ab, "*", 1, -1, "times"));
TRY(libab_register_operator_infix(ab, "/", 1, -1, "divide"));
2018-05-23 15:41:17 -07:00
libab_ref_free(&trig_type);
libab_ref_free(&atan2_type);
libab_ref_free(&difficult_type);
return result;
}
int main() {
char input_buffer[2048];
int interaction_count = INTERACTIONS;
libab_ref eval_into;
libab_ref call_into;
2018-05-23 15:41:17 -07:00
libab_result result;
libab_result eval_result;
libab ab;
2018-05-26 21:55:30 -07:00
if (libab_init(&ab, impl_parse, impl_free) != LIBAB_SUCCESS) {
2018-05-23 15:41:17 -07:00
fprintf(stderr, "Failed to initialize libab.\n");
exit(1);
}
result = register_functions(&ab);
2018-05-26 21:55:30 -07:00
while (interaction_count-- && result == LIBAB_SUCCESS) {
2018-05-23 15:41:17 -07:00
printf("(%d) > ", INTERACTIONS - interaction_count);
fgets(input_buffer, 2048, stdin);
eval_result = libab_run(&ab, input_buffer, &eval_into);
2018-05-26 21:55:30 -07:00
if (eval_result != LIBAB_SUCCESS) {
2018-05-23 15:41:17 -07:00
printf("Invalid input.\n");
} else {
result = libab_run_function(&ab, "print", &call_into, 1, &eval_into);
libab_ref_free(&call_into);
2018-05-23 15:41:17 -07:00
}
libab_ref_free(&eval_into);
}
libab_free(&ab);
}