DIRECTOR: Lingo: Made built-in functions generic

This commit is contained in:
Eugene Sandulenko 2016-08-05 22:01:57 +02:00
parent cdf3c9f89e
commit 464f360e97
5 changed files with 57 additions and 37 deletions

View File

@ -27,35 +27,37 @@ namespace Director {
static struct BuiltinProto { static struct BuiltinProto {
const char *name; const char *name;
void (*func)(void); void (*func)(void);
int nparams; int minArgs;
int maxArgs;
bool parens;
} builtins[] = { } builtins[] = {
// Math // Math
{ "abs", Lingo::b_abs, 1 }, { "abs", Lingo::b_abs, 1, 1, true },
{ "atan", Lingo::b_atan, 1 }, { "atan", Lingo::b_atan, 1, 1, true },
{ "cos", Lingo::b_cos, 1 }, { "cos", Lingo::b_cos, 1, 1, true },
{ "exp", Lingo::b_exp, 1 }, { "exp", Lingo::b_exp, 1, 1, true },
{ "float", Lingo::b_float, 1 }, { "float", Lingo::b_float, 1, 1, true },
{ "integer",Lingo::b_integer, 1 }, { "integer",Lingo::b_integer, 1, 1, true },
{ "log", Lingo::b_log, 1 }, { "log", Lingo::b_log, 1, 1, true },
{ "pi", Lingo::b_pi, 0 }, { "pi", Lingo::b_pi, 0, 0, true },
{ "power", Lingo::b_power, 2 }, { "power", Lingo::b_power, 2, 2, true },
{ "random", Lingo::b_random, 1 }, { "random", Lingo::b_random, 1, 1, true },
{ "sin", Lingo::b_sin, 1 }, { "sin", Lingo::b_sin, 1, 1, true },
{ "sqrt", Lingo::b_sqrt, 1 }, { "sqrt", Lingo::b_sqrt, 1, 1, true },
{ "tan", Lingo::b_tan, 1 }, { "tan", Lingo::b_tan, 1, 1, true },
// String // String
{ "chars", Lingo::b_chars, 3 }, { "chars", Lingo::b_chars, 3, 3, true },
{ "length", Lingo::b_length, 1 }, { "length", Lingo::b_length, 1, 1, true },
{ "string", Lingo::b_string, 1 }, { "string", Lingo::b_string, 1, 1, true },
// Misc // Misc
{ "closeDA", Lingo::b_closeDA, -1 }, { "closeDA", Lingo::b_closeDA, 0, 0, false },
{ "continue", Lingo::b_continue, -1 }, { "continue", Lingo::b_continue, 0, 0, false },
{ "dontpassevent", Lingo::b_dontpassevent, -1 }, { "dontpassevent", Lingo::b_dontpassevent, 0, 0, false },
{ "updatestage", Lingo::b_updatestage, -1 }, { "updatestage", Lingo::b_updatestage, 0, 0, false },
{ "ilk", Lingo::b_ilk, 1 }, { "ilk", Lingo::b_ilk, 1, 2, true },
// point // point
{ "point", Lingo::b_point, 2 }, { "point", Lingo::b_point, 2, 2, true },
{ 0, 0, 0 } { 0, 0, 0, 0, false }
}; };
void Lingo::initBuiltIns() { void Lingo::initBuiltIns() {
@ -65,7 +67,9 @@ void Lingo::initBuiltIns() {
sym->name = (char *)calloc(strlen(blt->name) + 1, 1); sym->name = (char *)calloc(strlen(blt->name) + 1, 1);
Common::strlcpy(sym->name, blt->name, strlen(blt->name)); Common::strlcpy(sym->name, blt->name, strlen(blt->name));
sym->type = BLTIN; sym->type = BLTIN;
sym->nargs = blt->nparams; sym->nargs = blt->minArgs;
sym->maxArgs = blt->maxArgs;
sym->parens = blt->parens;
sym->u.func = blt->func; sym->u.func = blt->func;
_handlers[blt->name] = sym; _handlers[blt->name] = sym;

View File

@ -740,10 +740,27 @@ void Lingo::c_call() {
g_lingo->_pc += g_lingo->calcStringAlignment(name.c_str()); g_lingo->_pc += g_lingo->calcStringAlignment(name.c_str());
int nargs = READ_UINT32(&(*g_lingo->_currentScript)[g_lingo->_pc++]); int nargs = READ_UINT32(&(*g_lingo->_currentScript)[g_lingo->_pc++]);
bool drop = false;
Symbol *sym;
if (!g_lingo->_handlers.contains(name)) { if (!g_lingo->_handlers.contains(name)) {
warning("Call to undefined handler '%s'. Dropping %d stack items", name.c_str(), nargs); warning("Call to undefined handler '%s'. Dropping %d stack items", name.c_str(), nargs);
drop = true;
} else {
sym = g_lingo->_handlers[name];
if (sym->type == BLTIN && sym->nargs != nargs && sym->maxArgs != nargs) {
if (sym->nargs == sym->maxArgs)
warning("Incorrect number of arguments to handler '%s', expecting %d. Dropping %d stack items", name.c_str(), sym->nargs, nargs);
else
warning("Incorrect number of arguments to handler '%s', expecting %d or %d. Dropping %d stack items", name.c_str(), sym->nargs, sym->maxArgs, nargs);
drop = true;
}
}
if (drop) {
for (int i = 0; i < nargs; i++) for (int i = 0; i < nargs; i++)
g_lingo->pop(); g_lingo->pop();
@ -753,8 +770,6 @@ void Lingo::c_call() {
return; return;
} }
Symbol *sym = g_lingo->_handlers[name];
if (sym->nargs < nargs) { if (sym->nargs < nargs) {
warning("Incorrect number of arguments for function %s. Dropping extra %d", name.c_str(), nargs - sym->nargs); warning("Incorrect number of arguments for function %s. Dropping extra %d", name.c_str(), nargs - sym->nargs);
for (int i = 0; i < nargs - sym->nargs; i++) for (int i = 0; i < nargs - sym->nargs; i++)
@ -762,15 +777,8 @@ void Lingo::c_call() {
} }
if (sym->type == BLTIN) { if (sym->type == BLTIN) {
if (sym->nargs > 0 && nargs < sym->nargs) { // FIXME. TODO. Pass nargs
warning("Too few arguments for function %s. Expecting %d but got %d", name.c_str(), sym->nargs, nargs);
for (int i = 0; i < nargs; i++)
g_lingo->pop();
g_lingo->pushVoid();
return;
}
(*sym->u.func)(); (*sym->u.func)();
return; return;

View File

@ -185,7 +185,10 @@ whitespace [\t ]
yylval.s = new Common::String(yytext); yylval.s = new Common::String(yytext);
if (g_lingo->_handlers.contains(yytext)) { if (g_lingo->_handlers.contains(yytext)) {
if (g_lingo->_handlers[yytext]->type == BLTIN && g_lingo->_handlers[yytext]->nargs == -1) if (g_lingo->_handlers[yytext]->type == BLTIN &&
g_lingo->_handlers[yytext]->nargs == 0 &&
g_lingo->_handlers[yytext]->maxArgs == 0 &&
!g_lingo->_handlers[yytext]->parens)
return BLTINNOARGS; return BLTINNOARGS;
} }

View File

@ -72,6 +72,8 @@ Symbol::Symbol() {
type = VOID; type = VOID;
u.s = NULL; u.s = NULL;
nargs = 0; nargs = 0;
maxArgs = 0;
parens = true;
global = false; global = false;
} }

View File

@ -89,7 +89,10 @@ struct Symbol { /* symbol table entry */
Common::String *s; /* STRING */ Common::String *s; /* STRING */
FloatArray *arr; /* ARRAY, POINT, RECT */ FloatArray *arr; /* ARRAY, POINT, RECT */
} u; } u;
int nargs; int nargs; /* number of arguments */
int maxArgs; /* maximal number of arguments, for builtins */
bool parens; /* whether parens required or not, for builitins */
bool global; bool global;
Symbol(); Symbol();