Fixed the GIB math evaluator to handle unary operators properly, made

indexing/clipping more like python, made some cosmetic changes to zoom.gib,
and added the ability for GIB builtins to return values.
This commit is contained in:
Brian Koropoff 2002-08-23 21:18:00 +00:00
parent 7bf21e20ed
commit 32f4e53aa5
7 changed files with 78 additions and 20 deletions

View file

@ -1,4 +1,4 @@
// zoom.rc
// zoom.gib
//
// zoom script for GIB in QuakeForge 0.5
//
@ -42,6 +42,7 @@ function "zoom.init" { // Initialize basic options
set in_amp ${zoom.amp}
}
// Default initial values
zoom.init 1 90 1 90 1.15
function "zoom.adjust" { // Adjust fov and sensitivity to match zoom factor

View file

@ -23,6 +23,7 @@
#define __ops_h
double OP_Not (double op1, double op2);
double OP_Negate (double op1, double op2);
double OP_Add (double op1, double op2);
double OP_Sub (double op1, double op2);
double OP_Mult (double op1, double op2);

View file

@ -36,6 +36,7 @@ optable_t optable[] =
{"!", OP_Not, 1},
{"**", OP_Exp, 2},
{"/", OP_Div, 2},
{"-", OP_Negate, 1},
{"*", OP_Mult, 2},
{"+", OP_Add, 2},
{"-", OP_Sub, 2},
@ -168,6 +169,16 @@ int EXP_DoFunction (token *chain)
return -2; // We shouldn't get here
}
int EXP_DoUnary (token *chain)
{
if (chain->generic.next->generic.type == TOKEN_OP)
EXP_DoUnary (chain->generic.next);
if (chain->generic.next->generic.type != TOKEN_NUM)
return -1; // In theory, this should never happen
chain->generic.next->num.value = chain->op.op->func(chain->generic.next->num.value, 0);
EXP_RemoveToken (chain);
return 0;
}
token *EXP_ParseString (char *str)
{
@ -250,6 +261,8 @@ token *EXP_ParseString (char *str)
i -= (m - strlen(op->str) + 1);
new = EXP_NewToken();
new->generic.type = TOKEN_OP;
if (*(op->str) == '-') // HACK HACK HACK
op = optable + 6; // Always assume subtraction for -
new->op.op = op;
new->generic.prev = cur;
new->generic.next = 0;
@ -317,6 +330,10 @@ exp_error_t EXP_SimplifyTokens (token *chain)
for (cur = chain->generic.next; cur->generic.type != TOKEN_CPAREN; cur = cur->generic.next)
{
if (cur->generic.type == TOKEN_OP && cur->op.op == optable + i && cur->generic.next) {
// If a unary operator is in our way, it gets evaluated early
if (cur->generic.next->generic.type == TOKEN_OP)
if (EXP_DoUnary (cur->generic.next))
return EXP_E_SYNTAX;
if (optable[i].operands == 1 && cur->generic.next->generic.type == TOKEN_NUM) {
cur->generic.next->num.value = optable[i].func(cur->generic.next->num.value, 0);
temp = cur;
@ -422,15 +439,7 @@ exp_error_t EXP_Validate (token *chain)
else if ((cur->generic.type == TOKEN_OP || cur->generic.type == TOKEN_OPAREN) && cur->generic.next->generic.type == TOKEN_OP)
{
if (cur->generic.next->op.op->func == OP_Sub) /* Stupid hack for negation */
{
cur = cur->generic.next;
cur->generic.type = TOKEN_NUM;
cur->num.value = -1.0;
new = EXP_NewToken();
new->generic.type = TOKEN_OP;
new->op.op = EXP_FindOpByStr ("*");
EXP_InsertTokenAfter (cur, new);
}
cur->generic.next->op.op = optable + 3;
else if (cur->generic.next->op.op->operands == 2)
return EXP_E_SYNTAX; /* Operator misuse */
}

View file

@ -162,6 +162,16 @@ GIB_Arg_Strip_Delim (unsigned int arg)
}
}
void
GIB_Return (const char *str)
{
if (GIB_DATA(cbuf_active)->type != GIB_BUFFER_PROXY)
return;
dstring_clearstr (GIB_DATA(cbuf_active->up)->ret.retval);
dstring_appendstr (GIB_DATA(cbuf_active->up)->ret.retval, str);
GIB_DATA(cbuf_active->up)->ret.available = true;
}
/*
GIB Builtin functions
@ -178,6 +188,22 @@ GIB_Function_f (void)
GIB_Function_Define (GIB_Argv(1), GIB_Argv(2));
}
void
GIB_FunctionDotGet_f (void)
{
if (GIB_Argc () != 2)
Cbuf_Error ("syntax",
"function.get: invalid syntax\n"
"usage: function.get function_name");
else {
gib_function_t *f;
if ((f = GIB_Function_Find (GIB_Argv (1))))
GIB_Return (f->program->str);
else
GIB_Return ("");
}
}
void
GIB_Local_f (void)
{
@ -335,6 +361,7 @@ void
GIB_Builtin_Init (void)
{
GIB_Builtin_Add ("function", GIB_Function_f, GIB_BUILTIN_NORMAL);
GIB_Builtin_Add ("function.get", GIB_FunctionDotGet_f, GIB_BUILTIN_NORMAL);
GIB_Builtin_Add ("export", GIB_Export_f, GIB_BUILTIN_NORMAL);
GIB_Builtin_Add ("local", GIB_Local_f, GIB_BUILTIN_NORMAL);
GIB_Builtin_Add ("global", GIB_Global_f, GIB_BUILTIN_NORMAL);

View file

@ -213,6 +213,11 @@ GIB_Parse_Extract_Line (struct cbuf_s *cbuf)
Cbuf_Error ("parse", "Could not find matching %c", c);
return;
}
} else if (dstr->str[i] == '`') {
if ((c = GIB_Parse_Match_Backtick (dstr->str, &i))) {
Cbuf_Error ("parse", "Could not find matching %c", c);
return;
}
} else if (dstr->str[i] == '\n' || dstr->str[i] == ';')
break;
else if (dstr->str[i] == '/' && dstr->str[i+1] == '/') {

View file

@ -64,7 +64,13 @@ GIB_Process_Index (dstring_t *index, unsigned int pos, int *i1, int *i2)
}
v1 = atoi (index->str+pos+1);
if ((p = strchr (index->str+pos, ':'))) {
v2 = atoi (p+1);
if (*(p+1) == ']')
v2 = -1;
else {
v2 = atoi (p+1);
if (v2 < 0)
v2--;
}
} else
v2 = v1;
dstring_snip (index, pos, i - pos + 1);
@ -140,9 +146,14 @@ GIB_Process_Variables_All (struct dstring_s *token)
token->str[i+n] == '_' ||
token->str[i+n] == '[' ||
token->str[i+n] == ':'; n++) {
if (token->str[i+n] == '[')
if (token->str[i+n] == '[') {
while (token->str[i+n] && token->str[i+n] != ']')
n++;
if (!token->str[i+n]) {
Cbuf_Error ("parse", "Could not find match for [");
goto ERROR;
}
}
}
dstring_insert (var, 0, token->str+i, n); // extract it
}
@ -172,15 +183,14 @@ GIB_Process_Variables_All (struct dstring_s *token)
i2 = 0;
} else if (i2 >= strlen (var->str))
i2 = strlen(var->str)-1;
if (i2 < i1) {
i1 ^= i2;
i2 ^= i1;
i1 ^= i2;
if (i2 < i1)
dstring_clearstr (var);
else {
if (i2 < strlen(var->str)-1) // Snip everthing after index 2
dstring_snip (var, i2+1, strlen(var->str)-i2-1);
if (i1 > 0) // Snip everything before index 1
dstring_snip (var, 0, i1);
}
if (i2 < strlen(var->str)-1) // Snip everthing after index 2
dstring_snip (var, i2+1, strlen(var->str)-i2-1);
if (i1 > 0) // Snip everything before index 1
dstring_snip (var, 0, i1);
}
dstring_replace (token, i, n, var->str, strlen(var->str));
i += strlen (var->str) - 1;

View file

@ -26,6 +26,11 @@ double OP_Not (double op1, double op2)
return !op1;
}
double OP_Negate (double op1, double op2)
{
return -op1;
}
double OP_Add (double op1, double op2)
{
return op1 + op2;