Skip to content

Commit

Permalink
More cleanup in eval_expression().
Browse files Browse the repository at this point in the history
  • Loading branch information
mikeakohn committed Oct 19, 2024
1 parent 7934a98 commit d0e4d44
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 77 deletions.
10 changes: 9 additions & 1 deletion common/Var.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class Var
{
}

Var(Var &v)
Var(const Var &v)
{
type = v.type;
value_int = v.value_int;
Expand All @@ -38,6 +38,14 @@ class Var
{
}

Var & operator= (const Var &s)
{
type = s.type;
value_int = s.value_int;

return *this;
}

template <typename TYPE>
TYPE get_data()
{
Expand Down
109 changes: 44 additions & 65 deletions common/eval_expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,19 @@
#include "common/Operator.h"
#include "common/tokens.h"

#define PRINT_STACK() \
{ \
int i; \
for (i = 0; i < var_stack_ptr; i++) printf("%d) %lx <-\n", i, var_stack[i].value_int); \
}

int EvalExpression::run(
AsmContext *asm_context,
Var &var,
Operator &last_operator)
Operator &last_oper)
{
char token[TOKENLEN];
int token_type;
Var var_stack[3];
int var_stack_ptr = 1;
VarStack var_stack;
Operator oper;
int last_token_was_op = -1;

#ifdef DEBUG
printf("Enter eval_expression, var=%d/%f/%d\n",
var.get_int32(),
var.get_float(),
var.get_type());
#endif

oper = last_operator;
var_stack[0] = var;
oper = last_oper;
var_stack.push(var);

while (true)
{
Expand All @@ -55,7 +41,7 @@ printf("eval_expression> token=%s var_stack_ptr=%d\n", token, var_stack_ptr);
#endif

// Issue 15: Return an error if a stack is full with no operator.
if (var_stack_ptr == 3 && oper.is_unset())
if (var_stack.size() == 3 && oper.is_unset())
{
return -1;
}
Expand All @@ -75,22 +61,23 @@ printf("eval_expression> token=%s var_stack_ptr=%d\n", token, var_stack_ptr);
{
if (last_token_was_op == 0 && oper.is_set())
{
last_operator.execute(
var_stack[var_stack_ptr - 2],
var_stack[var_stack_ptr - 1]);
last_oper.execute(
var_stack.get_second(),
var_stack.get_last());

var_stack_ptr--;
var_stack.pop();
oper.reset();

var = var_stack[var_stack_ptr - 1];
var = var_stack.pop();

tokens_push(asm_context, token, token_type);
return 0;
}

if (oper.is_unset() && var_stack_ptr == 2)
if (oper.is_unset() && var_stack.size() == 2)
{
// This is probably the x(r12) case.. so this is actually okay.
var = var_stack[var_stack_ptr - 1];
var = var_stack.pop();
tokens_push(asm_context, token, token_type);
return 0;
}
Expand All @@ -111,12 +98,12 @@ printf("eval_expression> token=%s var_stack_ptr=%d\n", token, var_stack_ptr);
printf("Paren got back %d/%f/%d\n", var_get_int32(&paren_var), var_get_float(&paren_var), var_get_type(&paren_var));
#endif

var_stack[var_stack_ptr++] = paren_var;
var_stack.push(paren_var);

token_type = tokens_get(asm_context, token, TOKENLEN);

// FIXME: if (IS_NOT_TOKEN(token, ')')
if (!(token[0] == ')' && token[1] == 0))
//if (!(token[0] == ')' && token[1] == 0))
if (IS_NOT_TOKEN(token, ')'))
{
print_error(asm_context, "No matching ')'");
return -1;
Expand All @@ -143,13 +130,11 @@ printf("Paren got back %d/%f/%d\n", var_get_int32(&paren_var), var_get_float(&pa

if (token_type == TOKEN_EOL)
{
//asm_context->tokens.line++;
tokens_push(asm_context, token, token_type);
break;
}

//printf("** token=%s %s\n", token, oper.to_string());
bool do_minus = false;
//bool do_minus = false;

#if 0
if (oper.is_set() && IS_TOKEN(token, '-'))
Expand All @@ -164,29 +149,24 @@ printf("Paren got back %d/%f/%d\n", var_get_int32(&paren_var), var_get_float(&pa
{
last_token_was_op = 0;

if (var_stack_ptr == 3)
if (var_stack.size() == 3)
{
print_error_unexp(asm_context, token);
return -1;
}

//printf("var_stack_ptr=%d\n", var_stack_ptr);

var_stack[var_stack_ptr].set_int(token);
if (do_minus) { var_stack[var_stack_ptr].negative(); }

var_stack_ptr++;
var_stack.push_int(token);
}
else
if (token_type == TOKEN_FLOAT)
{
if (var_stack_ptr == 3)
if (var_stack.size() == 3)
{
print_error_unexp(asm_context, token);
return -1;
}

var_stack[var_stack_ptr++].set_float(token);
var_stack.push_float(token);
}
else
if (token_type == TOKEN_SYMBOL)
Expand All @@ -212,22 +192,21 @@ printf("Paren got back %d/%f/%d\n", var_get_int32(&paren_var), var_get_float(&pa
return -1;
}

if (var_stack_ptr == 3)
if (var_stack.size() == 3)
{
print_error_unexp(asm_context, token);
return -1;
}

var_stack[var_stack_ptr++].set_int(num);
var_stack.push_int(num);

oper = operator_prev;
last_token_was_op = 0;

continue;
}

// Stack pointer probably shouldn't be less than 2.
if (var_stack_ptr == 0)
if (var_stack.is_empty())
{
printf("Error: Unexpected operator '%s' at %s:%d\n",
token,
Expand All @@ -236,30 +215,30 @@ printf("Paren got back %d/%f/%d\n", var_get_int32(&paren_var), var_get_float(&pa
return -1;
}

#ifdef DEBUG
printf("TOKEN %s: precedence %d %d\n", token, last_operator.precedence, oper.precedence);
#endif

if (last_operator.is_unset())
if (last_oper.is_unset())
{
last_operator = oper;
last_oper = oper;
}
else
if (last_operator.precedence > oper.precedence)
if (last_oper.precedence > oper.precedence)
{
if (run(asm_context, var_stack[var_stack_ptr - 1], oper) == -1)
Var var = var_stack.pop();

if (run(asm_context, var, oper) == -1)
{
return -1;
}

var_stack.push(var);
}
else
{
last_operator.execute(
var_stack[var_stack_ptr - 2],
var_stack[var_stack_ptr - 1]);
last_oper.execute(
var_stack.get_second(),
var_stack.get_last());

var_stack_ptr--;
last_operator = oper;
var_stack.pop();
last_oper = oper;
}
}
else
Expand All @@ -273,20 +252,20 @@ printf("TOKEN %s: precedence %d %d\n", token, last_operator.precedence, oper.pre
}

#ifdef DEBUG
printf("going to leave operation=%d\n", last_operator.operation);
printf("going to leave operation=%d\n", last_oper.operation);
PRINT_STACK()
#endif

if (last_operator.is_set())
if (last_oper.is_set())
{
last_operator.execute(
var_stack[var_stack_ptr - 2],
var_stack[var_stack_ptr - 1]);
last_oper.execute(
var_stack.get_second(),
var_stack.get_last());

var_stack_ptr--;
var_stack.pop();
}

var = var_stack[var_stack_ptr - 1];
var = var_stack.pop();

return 0;
}
Expand Down
47 changes: 36 additions & 11 deletions common/eval_expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,29 @@ class EvalExpression
return 0;
}

int size() { return ptr; }
int push_int(uint64_t value)
{
Var var;
var.set_int(value);
return push(var);
}

int push_int(const char *token)
{
Var var;
var.set_int(token);
return push(var);
}

int push_float(const char *token)
{
Var var;
var.set_float(token);
return push(var);
}

int size() { return ptr; }
bool is_empty() { return ptr == 0; }

int pop_first()
{
Expand All @@ -61,36 +83,39 @@ class EvalExpression
return 0;
}

int pop()
Var pop()
{
assert(ptr > 0);

ptr--;

return 0;
return stack[--ptr];
}

Var &get_first()
{
assert(ptr >= 1);

return stack[0];
}

Var &get_second()
{
assert(ptr >= 2);

return stack[ptr - 2];
}

Var &get_bottom()
Var &get_last()
{
assert(ptr >= 3);

assert(ptr >= 1);
return stack[ptr - 1];
}

void dump()
{
printf("-- var_stack %d --\n", ptr);
for (int n = 0; n < ptr; n++)
{
printf(" %d) %ld\n", n, stack[n].get_int64());
}
}

Var stack[3];
int ptr;
};
Expand Down
32 changes: 32 additions & 0 deletions tests/unit/eval_expression_ex/unit_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,29 @@

int errors = 0;

int get_int(const char *expression)
{
AsmContext asm_context;
Var var;

printf("Testing: %s\n", expression);

tokens_open_buffer(&asm_context, expression);
tokens_reset(&asm_context);

int ret = eval_expression(&asm_context, var);
int num = var.get_int32();

if (ret != 0)
{
printf("FAILED. (error evaluating)\n");
}

tokens_close(&asm_context);

return num;
}

void test_int(const char *expression, int answer)
{
AsmContext asm_context;
Expand Down Expand Up @@ -104,6 +127,14 @@ int main(int argc, char *argv[])
{
printf("eval_expression() test\n");

if (argc >= 2)
{
int n = get_int(argv[1]);
printf("Answer: %d\n", n);
exit(0);
}


test_int("-6", -6);
//test_int("6 + -5", 1);
//test_int("6 + -5 + -3", -2);
Expand All @@ -120,6 +151,7 @@ int main(int argc, char *argv[])
test_int("(106 - 100) / 2 - 2", 1);
test_int("6 / 2 - 2", 1);
test_int("6 * 2 - 2", 10);
test_int("8 * 4 / 2", 16);
test_int64("0xffffffff+1", 0x100000000);
test_int64("~0", -1);
test_int64("1 - ~0", 2);
Expand Down

0 comments on commit d0e4d44

Please sign in to comment.