int main(void){ Stack * stack; char * tempValue; int i; printf("\nCreating a new Stack"); stack = createStack("1"); tempValue = malloc(sizeof(char) * 128); for(i=2;i<101;i++){ sprintf(tempValue,"%d",i); stack = addToStack(tempValue,stack); } printf("\nThe value of the element on top of the stack is: %s",getTopValue(stack)); printf("\nPrinting the stack"); printStack(stack); printf("\nRemoving the top element of the stack, and printing again"); stack = removeFromTop(stack); printStack(stack); printf("\nThe value of the element on top of the stack is: %s",getTopValue(stack)); printf("\nDeleting the stack, and then printing again"); stack = deleteStack(stack); printStack(stack); printf("\nThe value of the element on top of the stack is: %s",getTopValue(stack)); printf("\nAttempting to delete an empty stack"); stack = deleteStack(stack); printf("\nAttempting to remove the top element of an empty stack"); stack = removeFromTop(stack); printf("\nAttempting to add an element to an empty stack"); stack = addToStack("1",stack); printf("\nThe value of the element on top of the stack is: %s",getTopValue(stack)); printf("\nPrinting the stack"); printStack(stack); printf("\nAdding an element with an empty value"); stack = addToStack(NULL,stack); printf("\nThe value of the element on top of the stack is: %s",getTopValue(stack)); printf("\nPrinting the stack"); printStack(stack); printf("\n"); return(0); }
Variant& StackMachine::evaluate(const VariableStore& store, const FunctionRegistry& functions) { reset(); for(const auto& instruction : _instructions) { switch(instruction._opCode) { case NOP: { break; } case PUSH: { _valueStack.emplace(instruction._value); break; } case PUSHVAR: { if(instruction._value.getType() != INT) { CSVSQLDB_THROW(StackMachineException, "expected an INT as variable index"); } int64_t index = instruction._value.asInt(); _valueStack.emplace(store[static_cast<size_t>(index)]); break; } case ADD: case SUB: case DIV: case MOD: case MUL: case EQ: case NEQ: case IS: case ISNOT: case GT: case GE: case LT: case LE: case AND: case OR: case CONCAT: { const Variant lhs(getNextValue()); Variant& rhs(getTopValue()); rhs = binaryOperation(mapOpCodeToBinaryOperationType(instruction._opCode), lhs, rhs); break; } case NOT: { Variant& rhs(getTopValue()); rhs = unaryOperation(OP_NOT, BOOLEAN, rhs); break; } case PLUS: { // this is a nop, as the value will not change, so just leave it on the stack break; } case MINUS: { Variant& rhs = getTopValue(); rhs = unaryOperation(OP_MINUS, rhs.getType(), rhs); break; } case BETWEEN: { const Variant lhs = getNextValue(); const Variant from = getNextValue(); Variant& to = getTopValue(); Variant result(BOOLEAN); if(not(lhs.isNull() || from.isNull() || to.isNull())) { if(binaryOperation(OP_GE, to, from).asBool()) { result = binaryOperation(OP_GE, lhs, from); if(result.asBool()) { result = binaryOperation(OP_LE, lhs, to); } } else { result = binaryOperation(OP_GE, lhs, to); if(result.asBool()) { result = binaryOperation(OP_LE, lhs, from); } } } to = result; break; } case FUNC: { if(instruction._value.getType() != STRING) { CSVSQLDB_THROW(StackMachineException, "expected a string as variable name"); } std::string funcname = instruction._value.asString(); Function::Ptr func = functions.getFunction(funcname); if(!func) { CSVSQLDB_THROW(StackMachineException, "function '" << funcname << "' not found"); } Variants parameter; size_t count = func->getParameterTypes().size(); for(const auto& param : func->getParameterTypes()) { Variant v = getNextValue(); if(param != v.getType()) { try { v = unaryOperation(OP_CAST, param, v); } catch(const std::exception&) { CSVSQLDB_THROW(StackMachineException, "calling function '" << funcname << "' with wrong parameter"); } } parameter.emplace(parameter.end(), v); --count; } if(count) { CSVSQLDB_THROW(StackMachineException, "too much parameters for function '" << funcname << "'"); } _valueStack.emplace(func->call(parameter)); break; } case CAST: { Variant& rhs = getTopValue(); rhs = unaryOperation(OP_CAST, instruction._value.getType(), rhs); break; } case IN: { size_t count = static_cast<size_t>(instruction._value.asInt()); const Variant lhs = getNextValue(); bool found(false); for(size_t n = 0; n < count; ++n) { Variant result = binaryOperation(OP_EQ, lhs, getNextValue()); if(result.asBool()) { found = true; ++n; for(; n < count; ++n) { // remove rest of the values from stack _valueStack.pop(); } break; } } if(found) { _valueStack.emplace(Variant(true)); } else { _valueStack.emplace(Variant(false)); } break; } case LIKE: { if(!instruction._r) { CSVSQLDB_THROW(StackMachineException, "expected a regexp in LIKE expression"); } Variant lhs = getTopValue(); if(lhs.getType() != STRING) { lhs = unaryOperation(OP_CAST, STRING, lhs); CSVSQLDB_THROW(StackMachineException, "can only do like operations on strings"); } if(instruction._r->match(lhs.asString())) { _valueStack.emplace(Variant(true)); } else { _valueStack.emplace(Variant(false)); } break; } } } return _valueStack.top(); }