/* * primitive.cc * * Created on: Feb 11, 2010 * Author: petergoodman * Version: $Id$ */ #include "primitive.h" namespace primitive { /** * Pop two tokens off of the stack and return them as a pair. */ pair take2(deque &stack) { Token *a(stack.back()); stack.pop_back(); Token *b(stack.back()); stack.pop_back(); return make_pair(a, b); } /* operators */ Token *op_add(Token *a, Token *b) { return new Token(Token::INT, a->int_val + b->int_val); } Token *op_sub(Token *a, Token *b) { return new Token(Token::INT, b->int_val - a->int_val); } Token *op_mul(Token *a, Token *b) { return new Token(Token::INT, a->int_val * b->int_val); } Token *op_div(Token *a, Token *b) { return new Token(Token::INT, b->int_val / a->int_val); } Token *op_eq(Token *a, Token *b) { return new Token( Token::INT, static_cast(a->int_val == b->int_val) ); } Token *op_gt(Token *a, Token *b) { return new Token(Token::INT, b->int_val > a->int_val); } Token *op_lt(Token *a, Token *b) { return new Token(Token::INT, b->int_val < a->int_val); } /** * Exit the interpreter. */ void exit(deque &stack, deque &tokens, map &symbols) { (void) stack; (void) tokens; (void) symbols; throw EXIT_SUCCESS; } /** * Free all tokens in the token stack. This can also be used to free the * token queue by passing it as the first argument. */ void clear(deque &stack, deque &tokens, map &symbols) { (void) tokens; (void) symbols; while(!stack.empty()) { delete stack.back(); stack.pop_back(); } } /** * Print the top token on the stack. */ void print(deque &stack, deque &tokens, map &symbols) { (void) tokens; (void) symbols; NotEmpty constraint(stack); Token *tok(stack.back()); if(tok->type == Token::INT) { cout << tok->int_val; } else { cout << tok->str_val; } } /** * Interpret the top element on the stack as code. This creates an * anonymous function, of sorts, and executes it immediately. */ void exec(deque &stack, deque &tokens, map &symbols) { And > constraint(stack); Token *tok(stack.back()); DerivedFunction<0> func(tok->str_val); func.call(stack, tokens, symbols); stack.pop_back(); delete tok; } /** * Pop the top token off of the stack and delete it. */ void pop(deque &stack, deque &tokens, map &symbols) { (void) tokens; (void) symbols; NotEmpty constraint(stack); Token *tok(stack.back()); stack.pop_back(); delete tok; } /** * Print all tokens on the stack. */ void dump(deque &stack, deque &tokens, map &symbols) { (void) tokens; (void) symbols; cout << "Stack (top-to-bottom):" << endl; for(deque::reverse_iterator it = stack.rbegin(), end = stack.rend(); it != end; it++) { cout << *it << endl; } } /** * Load the value of a variable store in the symbol table onto the stack. */ void load(deque &stack, deque &tokens, map &symbols) { (void) tokens; And > constraint(stack); Token *var(stack.back()); stack.pop_back(); if(symbols.end() == symbols.find(var->str_val)) { stringstream ss; ss << "Variable '" << var->str_val << "' has not been stored."; stack.push_back(var); throw runtime_error(ss.str()); } stack.push_back(new Token(symbols[var->str_val])); delete var; } /** * Store a token from the stack in the symbol table. */ void store(deque &stack, deque &tokens, map &symbols) { (void) tokens; And, Type > constraint(stack); pair both = take2(stack); if(symbols.end() != symbols.find(both.first->str_val)) { Token *old(symbols[both.first->str_val]); delete old; } symbols[both.first->str_val] = both.second; delete both.first; } /** * Store the value of a variable in the symbol table onto the stack. */ void cond(deque &stack, deque &tokens, map &symbols) { (void) symbols; And, And, And, Type > > > constraint(stack); pair consequent = take2(stack); Token *cond(stack.back()); stack.pop_back(); tokens.push_front(new Token(Token::FUNCTION, "exec")); if(cond->int_val != 0) { tokens.push_front(consequent.second); delete consequent.first; } else { tokens.push_front(consequent.first); delete consequent.second; } delete cond; } }