Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
20
Добавлен:
01.05.2014
Размер:
11.7 Кб
Скачать
#include <cmath>
#include <iostream>
#include <queue>
#include <vector>

#include "PolizInterpreter.hpp"
#include "Externs.hpp"
#include "Errors.hpp"
#include "TokenParser.hpp"

namespace Parser_impl {
	
	long double PolizInterpreter::getValue(LookupTable<Variable>& local)
	{
		PolizInstruction& in = exec_stack.top();
		exec_stack.pop();
		if (in.inst_type == TLiteral){
			return in.value;
		} else if (in.inst_type == TVariable) {
			if (in.local)
				return local.get(in.val).value;
			else
				return progr->global.get(in.val).value;
		} else 
			throw RuntimeException("Stack error");
		return 0.0;	
	}
	
	ElementTypes PolizInterpreter::getType(LookupTable<Variable>& local)
	{
		PolizInstruction in = exec_stack.top();
		if (in.inst_type == TLiteral){
			return ElementTypes(in.val);
		} else if (in.inst_type == TVariable) {
			if (in.local)
				return local.get(in.val).type;
			else
				return progr->global.get(in.val).type;
		} else 
			throw RuntimeException("Stack error");
		return VOID;
	}
	
	void PolizInterpreter::setValue(LookupTable<Variable>& local, long double v)
	{
		PolizInstruction& in = exec_stack.top();
		exec_stack.pop();
		
		if (in.inst_type == TVariable) {			
			if (in.local){
				Variable& var = local.get(in.val); 				
				var.value = (var.type == INT) ? ( (long long)v ):(v);
			} else {
				Variable& var = progr->global.get(in.val); 				
				var.value = (var.type == INT) ? ( (long long)v ):(v);
			}
		} else
			throw RuntimeException("Stack error");	
				 
	}
	
	std::string PolizInterpreter::getString()
	{
		PolizInstruction& in = exec_stack.top();
		exec_stack.pop();
		
		if (in.inst_type == TStrLit) {
			return in.str;
		} else
			throw RuntimeException("Stack error");
		
	}
	
	void PolizInterpreter::invoke(int f)
	{		
			
		unsigned cursor = 0;
		Function& func = progr->functions.get(f);
		LookupTable<Variable> local = func.local;
		
		if (f != progr->main && func.args_count > 0) {
			// Filling arguments of function f
			if (exec_stack.size()< unsigned(func.args_count))
				throw RuntimeException("Stack error");
				
			for (int i = func.args_count-1; i>=0; --i){
				Variable& v = local.get(i);
				long double d =getValue(local);
				v.value = (v.type == INT)? ((long long)d):d;
			}
			
		}
		
		bool was_return = false;
		
		while(cursor != func.code.size()){
			
			PolizInstruction instr = func.code[cursor]; 
			switch ( instr.inst_type ) {
				
				case TVariable:
				case TStrLit:
				case TLiteral:
					exec_stack.push(instr);
					break;
				
				
				case TFunction:{
					Function& f = progr->functions.get(instr.val);
					
					if (f.args_count >0) {
						std::vector<long double> vec(f.args_count);
						for (int i=0; i<f.args_count; ++i)
							vec[i] = getValue(local);
						for (int i=f.args_count-1; i>=0; --i){
							PolizInstruction in (TLiteral, FLOAT);
							in.value = vec[i];
							exec_stack.push(in);
						}
								
					}					
					invoke(instr.val);
					break;
				}
				
				case TIfNot: {
					
					long double v = getValue(local);
					
					if (v==0.0) {
						cursor = instr.val;
						continue;
					}
					break;
				}
					
				case TGoto: {
					cursor = instr.val;					
					continue;
				}
				
				case TReturn:{
					was_return = true;
					long double d = getValue(local);					
					PolizInstruction in(TLiteral);
					in.val = instr.val;
					in.value = (instr.val == INT)? ((long long)d) : (d);											
					exec_stack.push(in);	
					break;
				} 
				
				case TRead: {
					
					long double v;
					std::cin >> v;
						
					if (std::cin.fail()){
						global_error = 1;
						exec_stack.pop();
						break;
					}
					
					setValue(local, v);
					
					break;
				}
				
				case TWrite: {					
					
					int num = instr.val;
					
					std::deque<PolizInstruction> params;
					for (int i=0; i<num; ++i){
						params.push_front(exec_stack.top());
						exec_stack.pop();
					}
					
					if (debug)
						break;
					
					for (int i=0; i<num; ++i) {
						
						PolizInstruction& curr = params[i];
						if (curr.inst_type == TStrLit)
							std::cout << params[i].str;
						else if (curr.inst_type == TLiteral)
							std::cout << params[i].value;
						else if (curr.inst_type == TVariable){
							if (curr.local)
								std::cout << local.get(curr.val).value;
							else
								std::cout << progr->global.get(curr.val).value;
						}
																
					}
					
					break;
				}
				
				case TWasError:{
					PolizInstruction in(TLiteral);
					in.val = INT;
					in.value = global_error;
					exec_stack.push(in);
					global_error = 0;	
					break;
				}
				
				case TExit: {
					long double d = getValue(local);
					throw int(d);
				}
				
				case TPOP:
					exec_stack.pop(); 
					break;
				
				case TOperation:{
					
					switch (instr.val){
						
						case T_ASS: { 
							long double d = getValue(local);							
							setValue(local, d);							
							break;
						}
						
						case T_OR: {
							long double d1 = getValue(local);
							long double d2 = getValue(local);
							PolizInstruction in(TLiteral);
							in.val = INT;
							in.value = (d1 != 0.0 || d2 != 0.0) ? 1.0 : 0.0;
							exec_stack.push(in);
							break;
						}
						
						case T_AND: {
							long double d1 = getValue(local);
							long double d2 = getValue(local);
							PolizInstruction in(TLiteral);
							in.val = INT;
							in.value = (d1 != 0.0 && d2 != 0.0) ? 1.0 : 0.0;
							exec_stack.push(in);
							break;
						}
						
						case T_PLUS: {
							ElementTypes t1 = getType(local);
							long double d1 = getValue(local);
							ElementTypes t2 = getType(local);
							long double d2 = getValue(local);
							
							ElementTypes t = ( t1==FLOAT || t2==FLOAT) ? FLOAT:INT;
							PolizInstruction in(TLiteral);
							in.val = t;
							long double res = d1 + d2;
							in.value = (t == INT) ? ((long long)res) : res;
							exec_stack.push(in);
							break;
						}
						
						case T_MINUS: {
							ElementTypes t1 = getType(local);
							long double d1 = getValue(local);
							ElementTypes t2 = getType(local);
							long double d2 = getValue(local);
							
							ElementTypes t = ( t1==FLOAT || t2==FLOAT) ? FLOAT:INT;
							PolizInstruction in(TLiteral);
							in.val = t;
							long double res = d2 - d1;
							in.value = (t == INT) ? ((long long)res) : res;
							exec_stack.push(in);
							break;
						}
						
						case T_MUL: {
							ElementTypes t1 = getType(local);
							long double d1 = getValue(local);
							ElementTypes t2 = getType(local);
							long double d2 = getValue(local);
							
							ElementTypes t = ( t1==FLOAT || t2==FLOAT) ? FLOAT:INT;
							PolizInstruction in(TLiteral);
							in.val = t;
							long double res = d2*d1;
							in.value = (t == INT) ? ((long long)res) : res;
							exec_stack.push(in);
							break;
						}
						
						case T_DIV: {
							ElementTypes t1 = getType(local);
							long double d1 = getValue(local);
							ElementTypes t2 = getType(local);
							long double d2 = getValue(local);
							
							ElementTypes t = ( t1==FLOAT || t2==FLOAT) ? FLOAT:INT;
							PolizInstruction in(TLiteral);
							in.val = t;
							if (d1 == 0.0)
								throw RuntimeException("Division by zero");							
							long double res = 0.0;
							if (t == INT)
								res = ((long long)d2) / ((long long) d1);
							else
								res = d2/d1;
								
							in.value = res;
							exec_stack.push(in);
							break;
						}
						
						case T_MOD: {
							ElementTypes t1 = getType(local);
							long double d1 = getValue(local);
							ElementTypes t2 = getType(local);
							long double d2 = getValue(local);
							
							ElementTypes t = ( t1==FLOAT || t2==FLOAT) ? FLOAT:INT;
							if (t==FLOAT)
								throw RuntimeException("Operation '%' must have 'int' arguments");
								
							PolizInstruction in(TLiteral, INT);							
							if (d1 == 0.0)
								throw RuntimeException("Division by zero");							
							long double res = ((long long)d2) % ((long long) d1);							
								
							in.value = res;
							exec_stack.push(in);
							break;
						}
						
						case T_DEG: {
							ElementTypes t1 = getType(local);
							long double d1 = getValue(local);
							ElementTypes t2 = getType(local);
							long double d2 = getValue(local);
							
							ElementTypes t = ( t1==FLOAT || t2==FLOAT) ? FLOAT:INT;
							PolizInstruction in(TLiteral);
							in.val = t;
							long double res = std::pow(d2,d1);
							if (errno)
								throw RuntimeException("Bad arguments in degree operation");
							in.value = (t == INT) ? ((long long)res) : res;
							exec_stack.push(in);
							break;
						}
						
						case T_NOT: {							
							long double d1 = getValue(local);																				
							PolizInstruction in(TLiteral);
							in.val = INT;							
							in.value = (d1 == 0.0) ? 1.0 : 0.0;
							exec_stack.push(in);
							break;
						}
						
						case T_EQ: {
							long double d1 = getValue(local);
							long double d2 = getValue(local);
							PolizInstruction in(TLiteral);
							in.val = INT;
							in.value = (d1 == d2 ) ? 1.0 : 0.0;
							exec_stack.push(in);
							break;
						}
						
						case T_NEQ: {
							long double d1 = getValue(local);
							long double d2 = getValue(local);
							PolizInstruction in(TLiteral);
							in.val = INT;
							in.value = (d1 != d2 ) ? 1.0 : 0.0;
							exec_stack.push(in);
							break;
						}
						
						case T_LSS: {
							long double d1 = getValue(local);
							long double d2 = getValue(local);
							PolizInstruction in(TLiteral);
							in.val = INT;
							in.value = (d2 < d1 ) ? 1.0 : 0.0;
							exec_stack.push(in);
							break;
						}
						
						case T_LSSEQ: {
							long double d1 = getValue(local);
							long double d2 = getValue(local);
							PolizInstruction in(TLiteral);
							in.val = INT;
							in.value = (d2 <= d1 ) ? 1.0 : 0.0;
							exec_stack.push(in);
							break;
						}
						
						case T_GRT: {
							long double d1 = getValue(local);
							long double d2 = getValue(local);
							PolizInstruction in(TLiteral);
							in.val = INT;
							in.value = (d2 > d1 ) ? 1.0 : 0.0;
							exec_stack.push(in);
							break;
						}
						
						case T_GRTEQ: {
							long double d1 = getValue(local);
							long double d2 = getValue(local);
							PolizInstruction in(TLiteral);
							in.val = INT;
							in.value = (d2 >= d1 ) ? 1.0 : 0.0;
							exec_stack.push(in);
							break;
						}
						
						case T_MINUSUN: {
							ElementTypes t1 = getType(local);						
							long double d1 = getValue(local);																				
							PolizInstruction in(TLiteral);
							in.val = t1;							
							in.value = -d1;
							exec_stack.push(in);
							break;
						}
						
						case T_PLUSUN: {
							break;
						}
						
						default:;						
					} 
					
					break;
				}
				
				default:
					throw RuntimeException("Wrong Poliz command");
			}
			
			++cursor;
			
			if (was_return)
				break;
		}
		
		
		// Returning value
		
		if (func.return_type != VOID){
			if (!was_return){
				PolizInstruction in(TLiteral);
				in.val = func.return_type;
				in.value = 0.0;
				exec_stack.push(in);
			}
		}
									
	}
	
}
Соседние файлы в папке MyLanguage