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:
parent
4425b27b52
commit
ca6075e8d5
|
@ -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.
|
||||||
|
|
|
@ -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, ...);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, ¶ms, param_count, args);
|
result = _handle_va_params(ab, ¶ms, 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, ¶ms, into);
|
result = libab_interpreter_call_function(&ab->intr, &ab->table, function, ¶ms, into);
|
||||||
|
|
||||||
libab_ref_vec_free(¶ms);
|
libab_ref_vec_free(¶ms);
|
||||||
}
|
}
|
||||||
|
@ -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, ¶ms, param_count, args);
|
result = _handle_va_params(ab, ¶ms, 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, ¶ms, into);
|
result = libab_interpreter_call_function(&ab->intr, scope, function, ¶ms, into);
|
||||||
|
|
||||||
libab_ref_vec_free(¶ms);
|
libab_ref_vec_free(¶ms);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(¶ms);
|
||||||
|
} else {
|
||||||
|
result = LIBAB_BAD_CALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
free_params = 1;
|
||||||
|
result = libab_run_tree_scoped(ab, left, scope, ¶m);
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
result = libab_ref_vec_insert(¶ms, ¶m);
|
||||||
|
}
|
||||||
|
libab_ref_free(¶m);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(; index < right->children.size - 1 && result == LIBAB_SUCCESS; index++) {
|
||||||
|
result = libab_run_tree_scoped(ab, vec_index(&right->children, index),
|
||||||
|
scope, ¶m);
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
result = libab_ref_vec_insert(¶ms, ¶m);
|
||||||
|
}
|
||||||
|
libab_ref_free(¶m);
|
||||||
|
}
|
||||||
|
|
||||||
|
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, ¶ms, into);
|
||||||
|
} else {
|
||||||
|
libab_ref_null(into);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(free_params) {
|
||||||
|
libab_ref_vec_free(¶ms);
|
||||||
|
}
|
||||||
|
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
|
||||||
},
|
},
|
||||||
|
|
|
@ -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++);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user