Add a new method call operator, and more.

The '.' operator now represents method calls. A function f: (a, b)->c
can be called as a.f(b), which is equivalent to f(a, b). Besides
this change, all reserved operators now have a negative precedence
(it's relative, remember?), and some function names were changed.
This commit is contained in:
Danila Fedorin 2018-09-13 17:05:39 -07:00
parent 4425b27b52
commit ca6075e8d5
7 changed files with 103 additions and 13 deletions

View File

@ -70,11 +70,25 @@ libab_result libab_interpreter_run(libab_interpreter* intr, libab_tree* tree,
* @param into the reference to store the result into. * @param into the reference to store the result into.
* @return the result of the call. * @return the result of the call.
*/ */
libab_result libab_interpreter_run_function(libab_interpreter* intr, libab_result libab_interpreter_call_function(libab_interpreter* intr,
libab_ref* scope, libab_ref* scope,
const char* function, const char* function,
libab_ref_vec* params, libab_ref_vec* params,
libab_ref* into); libab_ref* into);
/**
* Calls a function value with the given parameters.
* @param intr the interpreter to use to call the function.
* @param scope the scope in which the function should be searched for.
* @param function the function to call.
* @param params the parameters to pass to the function.
* @param into the reference to store the result into.
* @return the result of the call.
*/
libab_result libab_interpreter_call_value(libab_interpreter* intr,
libab_ref* scope,
libab_ref* function,
libab_ref_vec* params,
libab_ref* into);
/** /**
* Gets the unit value from this interpreter. * Gets the unit value from this interpreter.
* @param intr the interpreter from which to get the unit value. * @param intr the interpreter from which to get the unit value.

View File

@ -263,7 +263,7 @@ libab_result libab_run_tree(libab* ab, libab_tree* tree, libab_ref* value);
* @param param_count the number of parameters given to this function. * @param param_count the number of parameters given to this function.
* @return the result of the call. * @return the result of the call.
*/ */
libab_result libab_run_function(libab* ab, const char* function, libab_result libab_call_function(libab* ab, const char* function,
libab_ref* into, libab_ref* into,
size_t param_count, ...); size_t param_count, ...);
/** /**
@ -293,7 +293,7 @@ libab_result libab_run_tree_scoped(libab* ab, libab_tree* tree, libab_ref* scope
* @param param_count the number of parameters given to this function. * @param param_count the number of parameters given to this function.
* @return the result of the call. * @return the result of the call.
*/ */
libab_result libab_run_function_scoped(libab* ab, const char* function, libab_ref* scope, libab_result libab_call_function_scoped(libab* ab, const char* function, libab_ref* scope,
libab_ref* into, libab_ref* into,
size_t param_count, ...); size_t param_count, ...);

View File

@ -198,7 +198,7 @@ libab_result loop(libab* ab, int interaction_count, libab_ref* scope) {
if (eval_result != LIBAB_SUCCESS) { if (eval_result != LIBAB_SUCCESS) {
printf("Invalid input (error code %d).\n", eval_result); printf("Invalid input (error code %d).\n", eval_result);
} else { } else {
result = libab_run_function_scoped(ab, "print", scope, &call_into, 1, &eval_into); result = libab_call_function_scoped(ab, "print", scope, &call_into, 1, &eval_into);
if(result == LIBAB_BAD_CALL) { if(result == LIBAB_BAD_CALL) {
printf("(?)\n"); printf("(?)\n");
result = LIBAB_SUCCESS; result = LIBAB_SUCCESS;

View File

@ -1297,7 +1297,7 @@ libab_result libab_interpreter_run(libab_interpreter* intr, libab_tree* tree,
return result; return result;
} }
libab_result libab_interpreter_run_function(libab_interpreter* intr, libab_result libab_interpreter_call_function(libab_interpreter* intr,
libab_ref* scope, libab_ref* scope,
const char* function, const char* function,
libab_ref_vec* params, libab_ref_vec* params,
@ -1322,6 +1322,21 @@ libab_result libab_interpreter_run_function(libab_interpreter* intr,
return result; return result;
} }
libab_result libab_interpreter_call_value(libab_interpreter* intr,
libab_ref* scope,
libab_ref* function,
libab_ref_vec* params,
libab_ref* into) {
struct interpreter_state state;
libab_result result = LIBAB_SUCCESS;
_interpreter_init(&state, intr, scope);
result = _interpreter_try_call(&state, function, params, into);
_interpreter_free(&state);
return result;
}
void libab_interpreter_unit_value(libab_interpreter* intr, libab_ref* into) { void libab_interpreter_unit_value(libab_interpreter* intr, libab_ref* into) {
libab_ref_copy(&intr->value_unit, into); libab_ref_copy(&intr->value_unit, into);
} }

View File

@ -377,7 +377,7 @@ libab_result libab_run(libab* ab, const char* string, libab_ref* value) {
return result; return result;
} }
libab_result libab_run_function(libab* ab, const char* function, libab_result libab_call_function(libab* ab, const char* function,
libab_ref* into, libab_ref* into,
size_t param_count, ...) { size_t param_count, ...) {
libab_ref_vec params; libab_ref_vec params;
@ -389,7 +389,7 @@ libab_result libab_run_function(libab* ab, const char* function,
result = _handle_va_params(ab, &params, param_count, args); result = _handle_va_params(ab, &params, param_count, args);
if(result == LIBAB_SUCCESS) { if(result == LIBAB_SUCCESS) {
libab_ref_free(into); libab_ref_free(into);
result = libab_interpreter_run_function(&ab->intr, &ab->table, function, &params, into); result = libab_interpreter_call_function(&ab->intr, &ab->table, function, &params, into);
libab_ref_vec_free(&params); libab_ref_vec_free(&params);
} }
@ -417,7 +417,7 @@ libab_result libab_run_scoped(libab* ab, const char* string, libab_ref* scope, l
return result; return result;
} }
libab_result libab_run_function_scoped(libab* ab, const char* function, libab_ref* scope, libab_ref* into, libab_result libab_call_function_scoped(libab* ab, const char* function, libab_ref* scope, libab_ref* into,
size_t param_count, ...) { size_t param_count, ...) {
libab_ref_vec params; libab_ref_vec params;
libab_result result; libab_result result;
@ -428,7 +428,7 @@ libab_result libab_run_function_scoped(libab* ab, const char* function, libab_re
result = _handle_va_params(ab, &params, param_count, args); result = _handle_va_params(ab, &params, param_count, args);
if(result == LIBAB_SUCCESS) { if(result == LIBAB_SUCCESS) {
libab_ref_free(into); libab_ref_free(into);
result = libab_interpreter_run_function(&ab->intr, scope, function, &params, into); result = libab_interpreter_call_function(&ab->intr, scope, function, &params, into);
libab_ref_vec_free(&params); libab_ref_vec_free(&params);
} }

View File

@ -41,6 +41,61 @@ libab_result _behavior_assign(libab* ab, libab_ref* scope,
return result; return result;
} }
libab_result _behavior_method(libab* ab, libab_ref* scope,
libab_tree* left, libab_tree* right,
libab_ref* into) {
libab_result result = LIBAB_SUCCESS;
libab_ref param;
libab_ref callee;
libab_ref_vec params;
int free_params = 0;
size_t index = 0;
libab_ref_null(&callee);
if(right->variant == TREE_CALL) {
result = libab_ref_vec_init(&params);
} else {
result = LIBAB_BAD_CALL;
}
if(result == LIBAB_SUCCESS) {
free_params = 1;
result = libab_run_tree_scoped(ab, left, scope, &param);
if(result == LIBAB_SUCCESS) {
result = libab_ref_vec_insert(&params, &param);
}
libab_ref_free(&param);
}
for(; index < right->children.size - 1 && result == LIBAB_SUCCESS; index++) {
result = libab_run_tree_scoped(ab, vec_index(&right->children, index),
scope, &param);
if(result == LIBAB_SUCCESS) {
result = libab_ref_vec_insert(&params, &param);
}
libab_ref_free(&param);
}
if(result == LIBAB_SUCCESS) {
libab_ref_free(&callee);
result = libab_run_tree_scoped(ab, vec_index(&right->children, right->children.size - 1),
scope, &callee);
}
if(result == LIBAB_SUCCESS) {
result = libab_interpreter_call_value(&ab->intr, scope, &callee, &params, into);
} else {
libab_ref_null(into);
}
if(free_params) {
libab_ref_vec_free(&params);
}
libab_ref_free(&callee);
return result;
}
libab_result _expect_boolean(libab* ab, libab_ref* scope, libab_result _expect_boolean(libab* ab, libab_ref* scope,
libab_tree* to_run, int* into) { libab_tree* to_run, int* into) {
libab_result result = LIBAB_SUCCESS; libab_result result = LIBAB_SUCCESS;
@ -103,19 +158,25 @@ libab_result _behavior_lor(libab* ab, libab_ref* scope,
static const libab_reserved_operator libab_reserved_operators[] = { static const libab_reserved_operator libab_reserved_operators[] = {
{ {
"=", /* Assignment */ "=", /* Assignment */
0, /* Lowest precedence */ -3, /* Lowest precedence */
1, /* Right associative, a = b = 6 should be a = (b = 6) */ 1, /* Right associative, a = b = 6 should be a = (b = 6) */
_behavior_assign _behavior_assign
}, },
{
".",
-2,
-1,
_behavior_method
},
{ {
"&&", /* Logical and */ "&&", /* Logical and */
0, /* Low precedence */ -1, /* Low precedence */
-1, /* Left associative. */ -1, /* Left associative. */
_behavior_land _behavior_land
}, },
{ {
"||", /* Logical or */ "||", /* Logical or */
0, /* Low precedence */ -1, /* Low precedence */
-1, /* Left associative. */ -1, /* Left associative. */
_behavior_lor _behavior_lor
}, },

View File

@ -572,7 +572,7 @@ void libab_sanitize(char* to, const char* from, size_t buffer_size) {
while (*from && index < (buffer_size - 2)) { while (*from && index < (buffer_size - 2)) {
if (*from == '+' || *from == '*' || *from == '\\' || if (*from == '+' || *from == '*' || *from == '\\' ||
*from == '|' || *from == '[' || *from == ']' || *from == '(' || *from == '|' || *from == '[' || *from == ']' || *from == '(' ||
*from == ')') *from == ')' || *from == '.')
to[index++] = '\\'; to[index++] = '\\';
to[index++] = *(from++); to[index++] = *(from++);
} }