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.
|
||||
* @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,
|
||||
const char* function,
|
||||
libab_ref_vec* params,
|
||||
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.
|
||||
* @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.
|
||||
* @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,
|
||||
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.
|
||||
* @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,
|
||||
size_t param_count, ...);
|
||||
|
||||
|
|
|
@ -198,7 +198,7 @@ libab_result loop(libab* ab, int interaction_count, libab_ref* scope) {
|
|||
if (eval_result != LIBAB_SUCCESS) {
|
||||
printf("Invalid input (error code %d).\n", eval_result);
|
||||
} 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) {
|
||||
printf("(?)\n");
|
||||
result = LIBAB_SUCCESS;
|
||||
|
|
|
@ -1297,7 +1297,7 @@ libab_result libab_interpreter_run(libab_interpreter* intr, libab_tree* tree,
|
|||
return result;
|
||||
}
|
||||
|
||||
libab_result libab_interpreter_run_function(libab_interpreter* intr,
|
||||
libab_result libab_interpreter_call_function(libab_interpreter* intr,
|
||||
libab_ref* scope,
|
||||
const char* function,
|
||||
libab_ref_vec* params,
|
||||
|
@ -1322,6 +1322,21 @@ libab_result libab_interpreter_run_function(libab_interpreter* intr,
|
|||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
libab_result libab_run_function(libab* ab, const char* function,
|
||||
libab_result libab_call_function(libab* ab, const char* function,
|
||||
libab_ref* into,
|
||||
size_t param_count, ...) {
|
||||
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);
|
||||
if(result == LIBAB_SUCCESS) {
|
||||
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);
|
||||
}
|
||||
|
@ -417,7 +417,7 @@ libab_result libab_run_scoped(libab* ab, const char* string, libab_ref* scope, l
|
|||
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, ...) {
|
||||
libab_ref_vec params;
|
||||
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);
|
||||
if(result == LIBAB_SUCCESS) {
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,61 @@ libab_result _behavior_assign(libab* ab, libab_ref* scope,
|
|||
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_tree* to_run, int* into) {
|
||||
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[] = {
|
||||
{
|
||||
"=", /* Assignment */
|
||||
0, /* Lowest precedence */
|
||||
-3, /* Lowest precedence */
|
||||
1, /* Right associative, a = b = 6 should be a = (b = 6) */
|
||||
_behavior_assign
|
||||
},
|
||||
{
|
||||
".",
|
||||
-2,
|
||||
-1,
|
||||
_behavior_method
|
||||
},
|
||||
{
|
||||
"&&", /* Logical and */
|
||||
0, /* Low precedence */
|
||||
-1, /* Low precedence */
|
||||
-1, /* Left associative. */
|
||||
_behavior_land
|
||||
},
|
||||
{
|
||||
"||", /* Logical or */
|
||||
0, /* Low precedence */
|
||||
-1, /* Low precedence */
|
||||
-1, /* Left associative. */
|
||||
_behavior_lor
|
||||
},
|
||||
|
|
|
@ -572,7 +572,7 @@ void libab_sanitize(char* to, const char* from, size_t buffer_size) {
|
|||
while (*from && index < (buffer_size - 2)) {
|
||||
if (*from == '+' || *from == '*' || *from == '\\' ||
|
||||
*from == '|' || *from == '[' || *from == ']' || *from == '(' ||
|
||||
*from == ')')
|
||||
*from == ')' || *from == '.')
|
||||
to[index++] = '\\';
|
||||
to[index++] = *(from++);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user