예제 #1
0
tagAXIS TabletSupport::normalPressureInfo() const
{
    int charLen = callFunc().ptrWTInfoA(WTI_DEVICES, DVC_NPRESSURE, NULL);
    tagAXIS buf;
    if(!charLen){
        return buf;
    }
    callFunc().ptrWTInfoA(WTI_DEVICES, DVC_NPRESSURE, &buf);
    return buf;
}
예제 #2
0
int TabletSupport::eventRate() const
{
    int charLen = callFunc().ptrWTInfoA(WTI_DEVICES, DVC_PKTRATE, NULL);
    UINT buf;
    if(!charLen){
        return buf;
    }
    callFunc().ptrWTInfoA(WTI_DEVICES, DVC_PKTRATE, &buf);
    return buf;
}
예제 #3
0
QString TabletSupport::deviceString() const
{
    int charLen = callFunc().ptrWTInfoA(WTI_DEVICES, DVC_NAME, NULL);
    if(!charLen){
        return QString();
    }
    TCHAR *buf = new TCHAR[charLen];
    callFunc().ptrWTInfoA(WTI_DEVICES, DVC_NAME, buf);
    QString info((char*)buf);
    delete [] buf;
    return info;
}
예제 #4
0
void aiscript::calcCall_threaded(GameTable* gameStat) {
	CodeConv::tostringstream o;
	o << _T("AIの副露判定に入ります。プレイヤー [") << (int)gameStat->CurrentPlayer.Passive << _T("]");
	info(o.str().c_str());
	gameStat->statOfPassive().DeclarationFlag.Chi = chiiNone; // リセット
	gameStat->statOfPassive().DeclarationFlag.Pon =
		gameStat->statOfPassive().DeclarationFlag.Kan =
		gameStat->statOfPassive().DeclarationFlag.Ron = false;
	if (callFunc(gameStat, gameStat->CurrentPlayer.Passive, fncname_call[gameStat->KangFlag.chankanFlag], (gameStat->KangFlag.chankanFlag == 0))) {
		return;
	} else {
		/* 実行完了 */
		int flag = 0;
		MeldCallID meldtype = (MeldCallID)lua_tointegerx(status[gameStat->CurrentPlayer.Passive].state, -2, &flag);
		if (!flag) {
			warn(_T("1番目の返り値が数値ではありません。無視します。"));
		} else {
			switch (meldtype) {
				case meldNone: break;
				case meldRon: gameStat->statOfPassive().DeclarationFlag.Ron = true; break;
				case meldKan: gameStat->statOfPassive().DeclarationFlag.Kan = true; break;
				case meldPon: gameStat->statOfPassive().DeclarationFlag.Pon = true; break;
				case meldChiiLower: gameStat->statOfPassive().DeclarationFlag.Chi = chiiLower; break;
				case meldChiiMiddle: gameStat->statOfPassive().DeclarationFlag.Chi = chiiMiddle; break;
				case meldChiiUpper: gameStat->statOfPassive().DeclarationFlag.Chi = chiiUpper; break;
				default: warn(_T("1番目の返り値が正しくありません。無視します。")); break;
			}
		}
		lua_pop(status[gameStat->CurrentPlayer.Passive].state, 1);
		return;
	}
}
void CommandHandler::invokeCommand(const int type,
                                   const std::string &args)
{
    if (type < 0 || type >= END_COMMANDS)
        return;
    callFunc(commands[type], args, nullptr);
}
void CommandHandler::invokeCommand(const int type,
                                   ChatTab *const tab)
{
    if (type < 0 || type >= END_COMMANDS)
        return;
    callFunc(commands[type], "", tab);
}
예제 #7
0
TabletSupport::TabletSupport(QWidget *window)
      :wintab_module(nullptr),
      window_(window),
      logContext(nullptr)
{
    if(!loadWintab()) {
        return;
    }
    if(!mapWintabFuns()){
        qCritical()<<"Error with function mapping!";
        return;
    }
    if(!hasDevice()){
        qCritical()<<"No Device found!";
        return;
    }
    logContext = new tagLOGCONTEXTA;
    auto handle = (HWND)window_->winId();

    callFunc().ptrWTInfoA(WTI_DEFSYSCTX, 0, logContext);
    logContext->lcOptions |= CXO_MESSAGES;
    logContext->lcMoveMask = PACKETDATA;
    logContext->lcBtnUpMask = logContext->lcBtnDnMask;

    AXIS TabletX;
    AXIS TabletY;
    callFunc().ptrWTInfoA( WTI_DEVICES, DVC_X, &TabletX );
    callFunc().ptrWTInfoA( WTI_DEVICES, DVC_Y, &TabletY );

    logContext->lcInOrgX = 0;
    logContext->lcInOrgY = 0;
    logContext->lcInExtX = TabletX.axMax;
    logContext->lcInExtY = TabletY.axMax;

    /* output the data in screen coords */
    logContext->lcOutOrgX = logContext->lcOutOrgY = 0;
    logContext->lcOutExtX = GetSystemMetrics(SM_CXSCREEN);
    /* move origin to upper left */
    logContext->lcOutExtY = -GetSystemMetrics(SM_CYSCREEN);

    logContext->lcPktData = PACKETDATA;
    logContext->lcPktMode = PACKETMODE;

    tabapis.context_ = callFunc().ptrWTOpenA(handle,
                                             (LPLOGCONTEXTA)logContext,
                                             true);
}
void CommandHandler::invokeCommand(const int type,
                                   const std::string &args,
                                   ChatTab *const tab)
{
    if (type < 0 || type >= END_COMMANDS)
        return;
    callFunc(commands[type], args, tab);
}
예제 #9
0
파일: Epoll.cpp 프로젝트: minamotoshi/web
void Epoll::callFunction(int code, Client* client, Json::Value &obj) {
	std::map<int, actionFunc>::iterator funcPointer = _messageFunc.find(code);
	if (funcPointer != _messageFunc.end()) {
		actionFunc callFunc = funcPointer->second;
		callFunc(client, obj);
	} else {
		std::cout << "invalid code:" << code << std::endl;
	}
}
예제 #10
0
static void buildin_pcall(const vector<LuaValue>& args, vector<LuaValue>& rets) {
    try {
        vector<LuaValue> _args(args.begin() + 1, args.end());
        callFunc(args[0], _args, rets);
        rets.insert(rets.begin(), LuaValue::TRUE);
    } catch(const exception& e) {
        rets.push_back(LuaValue::FALSE);
        rets.push_back(LuaValue(e.what()));
    }
}
예제 #11
0
void callFunc(const LuaValue& func, const vector<LuaValue>& args, vector<LuaValue>& rets) {
    auto stack = LuaVM::instance()->getCurrentStack();
    auto &values = stack->values();
    int funcIdx = (int)values.size();
    values.push_back(func);
    values.insert(values.end(), args.begin(), args.end());
    auto frame = stack->topFrame();
    callFunc(funcIdx, (int)args.size(), 0);
    execute(frame);
    rets.assign(values.begin() + funcIdx, values.begin() + funcIdx + frame->getExtCount());
    values.resize(funcIdx);
}
예제 #12
0
void ZaScreenCatalog::processEvent(ZaEvent *env)
{
	if (env->m_type == 100)
	{
		eventtest(env);
	}
	ZaObj * l_obj = env->m_obj;
//	fprintf(stderr,"-ZaScreenMain::processEvent-%p-%p-%d-%d-%d---\n",l_obj,this,env->m_type, env->m_x,env->m_y);
	fflush(stderr);
	if (l_obj && l_obj != this)
	{
		l_obj->processEvent(env);
		callFunc(l_obj,env);
	}
}
예제 #13
0
파일: native.cpp 프로젝트: isgiker/hhvm
TypedValue* methodWrapper(ActRec* ar) {
  auto func = ar->m_func;
  auto numArgs = func->numParams();
  auto numNonDefault = ar->numArgs();
  bool isStatic = func->isStatic();
  assert(!func->hasVariadicCaptureParam());
  TypedValue* args = ((TypedValue*)ar) - 1;
  TypedValue rv;
  rv.m_type = KindOfNull;

  if (LIKELY(numNonDefault == numArgs) ||
      LIKELY(nativeWrapperCheckArgs(ar))) {
    if (coerceFCallArgs(args, numArgs, numNonDefault, func)) {

      // Prepend a context arg for methods
      // KindOfClass when it's being called statically Foo::bar()
      // KindOfObject when it's being called on an instance $foo->bar()
      TypedValue ctx;
      if (ar->hasThis()) {
        if (isStatic) {
          throw_instance_method_fatal(getInvokeName(ar)->data());
        }
        ctx.m_type = KindOfObject;
        ctx.m_data.pobj = ar->getThis();
      } else {
        if (!isStatic) {
          throw_instance_method_fatal(getInvokeName(ar)->data());
        }
        ctx.m_type = KindOfClass;
        ctx.m_data.pcls = const_cast<Class*>(ar->getClass());
      }

      callFunc(func, &ctx, args, numArgs, rv);
    } else if (func->attrs() & AttrParamCoerceModeFalse) {
      rv.m_type = KindOfBoolean;
      rv.m_data.num = 0;
    }
  }

  assert(rv.m_type != KindOfUninit);
  if (isStatic) {
    frame_free_locals_no_this_inl(ar, func->numLocals(), &rv);
  } else {
    frame_free_locals_inl(ar, func->numLocals(), &rv);
  }
  tvCopy(rv, ar->m_r);
  return &ar->m_r;
}
예제 #14
0
PyObject* signalCall(PyObject* self, PyObject* args, PyObject* kw)
{
    PySideSignal* signal = reinterpret_cast<PySideSignal*>(self);

    if (!signal->homonymousMethod) {
        PyErr_SetString(PyExc_TypeError, "native Qt signal is not callable");
        return 0;
    }

    descrgetfunc getDescriptor = signal->homonymousMethod->ob_type->tp_descr_get;
    Shiboken::AutoDecRef homonymousMethod(getDescriptor(signal->homonymousMethod, 0, 0));

    if (PyCFunction_GET_FLAGS(homonymousMethod.object()) & METH_STATIC)
        return PyCFunction_Call(homonymousMethod, args, kw);

    ternaryfunc callFunc = signal->homonymousMethod->ob_type->tp_call;
    return callFunc(homonymousMethod, args, kw);
}
void CommandHandler::invokeCommand(const std::string &type,
                                   const std::string &args,
                                   ChatTab *const tab,
                                   const bool warn) const
{
    const CommandsMapIter it = mCommands.find(type);
    if (it != mCommands.end())
    {
        callFunc(*(*it).second, args, tab);
    }
    else if (!tab->handleCommand(type, args))
    {
        if (warn)
        {
            // TRANSLATORS: chat commands handling message
            tab->chatLog(_("Unknown command."));
        }
    }
}
예제 #16
0
void evaluateASTNodeSubMatrix(ASTNode *node){
	switch (node->subType) {
        case SubMatrixVectorExp:
			#ifdef DEBUGGING_ON
			printf("evaluate SubMatrixVectorExp!\n");
            #endif			
			node->l->mat = createBracketedMatrix(node->l->start,node->l->step,node->l->end);
			node->mat = cloneMatrix(node->l->mat);
			break;        
		case SubMatrixID:
			node->mat = callFunc(node->l->identifier, node->r);
			break;
		case SubMatrixNumber:
			node->mat = createSingletonMatrix(node->l->scalarValue);
			break;
        default:
            break;
    }
    return;
}
예제 #17
0
bool TabletSupport::supportTilt() const
{
    // Get info. about tilt
    struct tagAXIS tiltOrient[3];
    bool tiltSupport = false;
    tiltSupport = callFunc().ptrWTInfoA(WTI_DEVICES,
                                        DVC_ORIENTATION,
                                        &tiltOrient);
    if (tiltSupport){
        // Does the tablet support azimuth and altitude
        if (tiltOrient[0].axResolution && tiltOrient[1].axResolution){
            // Get resolution
            //            auto azimuth = tiltOrient[0].axResolution;
            //            auto altitude = tiltOrient[1].axResolution;
        }else{
            tiltSupport = false;
        }
    }
    return tiltSupport;
}
예제 #18
0
bool mainWindow::commandLineKeyPress(GdkEventKey* event)
{
	switch(event->keyval)
	{
		case GDK_KEY_Return:
			
			if(callFunc(commandLine->get_text()) == FUNC_NOT_FOUND)
			{
				equation *tmp = this->createEqFromStr(commandLine->get_text());
			
				if(tmp != 0)
				{
					eqView->addEquation(tmp);
					gV->redraw();
				}
			}
			
			return true;
			break;
	}
	return false;
}
예제 #19
0
void aiscript::calcDiscard_threaded(DiscardTileNum& answer, const GameTable* gameStat) {
	CodeConv::tostringstream o;
	o << _T("AIの打牌処理に入ります。プレイヤー [") << (int)gameStat->CurrentPlayer.Active << _T("]");
	info(o.str().c_str());
	if (callFunc(gameStat, gameStat->CurrentPlayer.Active, fncname_discard, true)) {
		answer = DiscardThrough;
		return;
	} else {
		/* 実行完了 */
		int flag;
		answer.type = (DiscardTileNum::discardType)lua_tointegerx(status[gameStat->CurrentPlayer.Active].state, -2, &flag);
		if (!flag) {
			warn(_T("1番目の返り値が数値ではありません。通常の打牌とみなします。"));
			answer.type = DiscardTileNum::Normal; // fallback
		} else if ((answer.type < DiscardTileNum::Normal) || (answer.type > DiscardTileNum::Disconnect)) {
			warn(_T("1番目の返り値が正しくありません。通常の打牌とみなします。"));
			answer.type = DiscardTileNum::Normal; // fallback
		}
		if ((answer.type == DiscardTileNum::Agari) || (answer.type == DiscardTileNum::Kyuushu) ||
			(answer.type == DiscardTileNum::Disconnect)) { // 番号指定が不要な場合
				answer.id = NumOfTilesInHand - 1; // 2番めの返り値は無視
		} else {
			int i = lua_tointegerx(status[gameStat->CurrentPlayer.Active].state, -1, &flag);
			if (!flag) {
				warn(_T("2番目の返り値が数値ではありません。ツモ切りとみなします。"));
				answer.id = NumOfTilesInHand - 1; // fallback
			} else if ((i >= 1)&&(i <= NumOfTilesInHand)) {
				answer.id = i - 1; // オリジンを1にする仕様……
			} else if ((i <= -1)&&(i >= -((int)NumOfTilesInHand))) { // マイナスを指定した場合の処理
				answer.id = NumOfTilesInHand + i;
			} else {
				warn(_T("2番目の返り値が範囲外です。ツモ切りとみなします。"));
				answer.id = NumOfTilesInHand - 1; // fallback
			}
		}
		lua_pop(status[gameStat->CurrentPlayer.Active].state, 2);
		return;
	}
}
예제 #20
0
파일: native.cpp 프로젝트: isgiker/hhvm
TypedValue* functionWrapper(ActRec* ar) {
  auto func = ar->m_func;
  auto numArgs = func->numParams();
  auto numNonDefault = ar->numArgs();
  assert(!func->hasVariadicCaptureParam());
  TypedValue* args = ((TypedValue*)ar) - 1;
  TypedValue rv;
  rv.m_type = KindOfNull;

  if (LIKELY(numNonDefault == numArgs) ||
      LIKELY(nativeWrapperCheckArgs(ar))) {
    if (coerceFCallArgs(args, numArgs, numNonDefault, func)) {
      callFunc(func, nullptr, args, numArgs, rv);
    } else if (func->attrs() & AttrParamCoerceModeFalse) {
      rv.m_type = KindOfBoolean;
      rv.m_data.num = 0;
    }
  }

  assert(rv.m_type != KindOfUninit);
  frame_free_locals_no_this_inl(ar, func->numLocals(), &rv);
  tvCopy(rv, ar->m_r);
  return &ar->m_r;
}
예제 #21
0
파일: gua.c 프로젝트: lengbing/gua
int callGoFunc (lua_State *L) {
    return callFunc(L, lua_tointeger(L, lua_upvalueindex(1)));
}
예제 #22
0
bool TabletSupport::hasDevice() const
{
    return callFunc().ptrWTInfoA(0, 0, NULL);
}
예제 #23
0
static void buildin_dofile(const vector<LuaValue>& args, vector<LuaValue>& rets) {
    callFunc(loadFile(args[0].getString()->buf()), vector<LuaValue>(), rets);
}
예제 #24
0
bool LuaSimpleContext::callFunc( const char* name, bool ignore_non_existent )
{
    FunctionCallArgs args;
    return callFunc(name, args, ignore_non_existent);
}
예제 #25
0
void LuaSimpleContext::tryCallFunc( const char* name )
{
    callFunc(name, true);
}
예제 #26
0
void aiscript::initcall(const GameTable* const gameStat, PlayerID player) {
	callFunc(gameStat, player, "init", false);
}
예제 #27
0
파일: test.cpp 프로젝트: HoriaCr/Algorithms
		returnType delayedDispatch() {
			return callFunc(typename Gens<sizeof...(Args)>::type());
		}
예제 #28
0
bool TabletSupport::nativeEventFilter(const QByteArray &eventType,
                                      void *message, long *)
{
    if (eventType == "windows_generic_MSG") {
        MSG* ev = static_cast<MSG *>(message);
        switch(ev->message){
        case WT_PACKET:
            PACKET pkt;
            if(!callFunc().ptrWTPacket((HCTX)ev->lParam,
                                       ev->wParam,
                                       &pkt)){
                return false;
            }
            QPointF new_point(pkt.pkX, pkt.pkY);
            QPointF window_point = window_->mapFromGlobal(new_point.toPoint());;

            auto preRange_s = normalPressureInfo();
            int preRange = preRange_s.axMax - preRange_s.axMin +1;
            auto tpreRange_s = tangentialPressureInfo();
            int tpreRange = tpreRange_s.axMax - tpreRange_s.axMin +1;

            auto btn_state = HIWORD(pkt.pkButtons);
            if(btn_state == TBN_DOWN) {
                QTabletEvent te(QEvent::TabletPress,
                                window_point,
                                new_point,
                                QTabletEvent::Stylus,
                                QTabletEvent::Pen,
                                pkt.pkNormalPressure/qreal(preRange),
                                0,// TODO: xTilt
                                0,// TODO: yTilt
                                // tangentialPressure
                                pkt.pkTangentPressure/qreal(tpreRange),
                                0.0,// TODO: rotation
                                0,// z
                                Qt::NoModifier, // TODO: get modfier
                                0// TODO: uniqueID
                                );
                qApp->sendEvent(window_, &te);
//                qDebug()<<"TabletPress";
            }else if(btn_state == TBN_UP){
                QTabletEvent te(QEvent::TabletRelease,
                                window_point,
                                new_point,
                                QTabletEvent::Stylus,
                                QTabletEvent::Pen,
                                pkt.pkNormalPressure/qreal(preRange),
                                0,// TODO: xTilt
                                0,// TODO: yTilt
                                // tangentialPressure
                                pkt.pkTangentPressure/qreal(tpreRange),
                                0.0,// TODO: rotation
                                0,// z
                                Qt::NoModifier, // TODO: get modfier
                                0// TODO: uniqueID
                                );
                qApp->sendEvent(window_, &te);
//                qDebug()<<"TabletRelease";
            }else{
                if( !new_point.isNull() ){
                    QTabletEvent te(QEvent::TabletMove,
                                    window_point,
                                    new_point,
                                    QTabletEvent::Stylus,
                                    QTabletEvent::Pen,
                                    pkt.pkNormalPressure/qreal(preRange),
                                    0,// TODO: xTilt
                                    0,// TODO: yTilt
                                    // tangentialPressure
                                    pkt.pkTangentPressure/qreal(tpreRange),
                                    0.0,// TODO: rotation
                                    pkt.pkZ,// z
                                    Qt::NoModifier, // TODO: get modfier
                                    0// TODO: uniqueID
                                    );
                    qApp->sendEvent(window_, &te);
//                    qDebug()<<"TabletMove";
                }
            }
            return true;
            break;
        }
    }
    return false;
}
예제 #29
0
파일: ast.c 프로젝트: LaurenceGA/arm
void execute(astNode *root) {
	if (SHOWTREE) {		// Set by cmd line option
		printTree(root, 0, false);
	}
	
	if (root == NULL) return;
	if (root->type == ASGN_nd) {
		// The symbol we're assigning to
		Symbol *s = root->op.left->sym;
		if (s->cnst) {
			fprintf(stderr, "Cannot assign to constant value '%s'\n", s->name);
			abort();
		}

		if (root->op.right->type == STR_nd) {
			if (s->varType == STRING)
				free(s->str);
			s->type = VAR;
			s->varType = STRING;
			s->str = (char *) malloc(strlen(root->op.right->str)+1);
			if (s->str == NULL) {
				fprintf(stderr, "Str memory allocation failed\n");
				abort();
			}
			strcpy(s->str, root->op.right->str);
			// s->str = root->op.right->str;
		} else if (root->op.right->type == VAR_nd &&
				root->op.right->sym->varType == STRING) {
		   if (s->varType == STRING)
			   free(s->str);
		   s->type = VAR;
		   s->varType = STRING;

		   char *rstr = root->op.right->sym->str;
		   s->str = (char *) malloc(strlen(rstr)+1);
		   if (s->str == NULL) {
				fprintf(stderr, "Str memory allocation failed\n");
				abort();
		   }
		   strcpy(s->str, rstr);
		   // s->str = root->op.right->sym->str;
		} else {
			s->type = VAR;
			s->varType = NUMBER;
			if (root->next != NULL) {
				switch (root->next->type) {
					case ADD_nd:
						s->val += getValue(root->op.right);
						break;
					case SUB_nd:
						s->val -= getValue(root->op.right);
						break;
					case MUL_nd:
						s->val *= getValue(root->op.right);
						break;
					case DIV_nd:
						s->val /= getValue(root->op.right);
						break;
					case MOD_nd:
						s->val = (int) s->val % (int) getValue(root->op.right);
						break;
					case EXP_nd:
						s->val = pow(s->val, getValue(root->op.right));
						break;

					default:
						// Shouldn't happen
						break;
				}
			} else {
				s->val = getValue(root->op.right);
			}
		}
	} else if (root->type == FUNCDEC_nd) {
		Symbol *s = root->op.left->sym;
		if (s->cnst) {
			fprintf(stderr, "Cannot create function with constant variable name '%s'\n", s->name);
			abort();
		}

		s->type = FUNCTION;
		s->code = root->op.right;
		s->templt->args = root->next;
		for (astNode *n=root->next; n != NULL; n=n->next) {
			s->templt->nargs++;
		}
		// printf("%d arguments\n", s->templt->nargs);
	} else if (root->type == FNC_nd) {
		callFunc(root);
	} else if (root->type == IF_nd) {
		if (getValue(root->next) != 0) {
			execute(root->op.left);
		} else if (root->op.right != NULL) {
			execute(root->op.right);
		}
	} else if (root->type == WHILE_nd) {
		while (getValue(root->op.left) != 0) {
			execute(root->op.right);
			if (cont) {
				cont = false;
				continue;
			}
			if (brk) {
				brk = false;
				break;
			}
		}
	} else if (root->type == STATEMENT_nd) {
		if (root->op.left != NULL) {
			execute(root->op.left);
		}
		if (!cont && !brk && !retrn) {
			if (root->next != NULL) {
				execute(root->next);
			}
		}
	} else if (root->type == BREAK_nd) {
		brk = true;
	} else if (root->type == CONTINUE_nd) {
		cont = true;
	} else if (root->type == RETRN_nd) {
		if (root->next->type == STR_nd) {
			setReturn(STRING, 0, root->next->str);
		} else {
			setReturn(NUMBER, getValue(root->next), NULL);
		}
		retrn = true;
	} else if (root->type == PRINT_nd) {
		if (root->next != NULL) {
			for (astNode *p = root->next; p != NULL; p = p->next) {
				if (p->op.left != NULL) {
					if (p->op.left->type == STR_nd) {
						printf("%s", p->op.left->str);
					} else {
						if (p->op.left->type == VAR_nd) {
							if (p->op.left->sym->varType == NUMBER) {
								printf("%g", getValue(p->op.left));
							} else {
								printf("%s", p->op.left->sym->str);
							}
						} else if (p->op.left->type == FNC_nd) {
							Frame *frm = callFunc(root);
							if (retrn) {
								retrn  = false;
								if (frm->retrn.type == NUMBER) {
									printf("%g", frm->retrn.val);
								} else {
									printf("%s", frm->retrn.str);
								}
							} else {
								fprintf(stderr, "Nothing returned!\n");
								abort();
							}
						} else
							printf("%g", getValue(p->op.left));
					}
				} else {
					fprintf(stderr, "Empty argument node\n");
					abort();
				}
			}
		} else printf("\n");
	} else if (root->type != STR_nd) {
		getValue(root);
	}
}
예제 #30
0
파일: ast.c 프로젝트: LaurenceGA/arm
double getValue(astNode *root) {
	switch (root->type) {
		case NUM_nd:
			return root->value;
			break;
		
		case ADD_nd:
			return getValue(root->op.left) + getValue(root->op.right);
			break;

		case SUB_nd:
			return getValue(root->op.left) - getValue(root->op.right);
			break;

		case MUL_nd:
			return getValue(root->op.left) * getValue(root->op.right);
			break;

		case DIV_nd:
			{
				double rval = getValue(root->op.right);
				if (rval == 0) {
					fprintf(stderr, "Divison by 0.\n");
					abort();
				}
				return getValue(root->op.left) / rval;
			}
			break;

		case EXP_nd:
			return pow(getValue(root->op.left), getValue(root->op.right));
			break;
		
		case MOD_nd:
			return (int) getValue(root->op.left) % (int) getValue(root->op.right);
			break;

		case NEG_nd:
			return -getValue(root->next);
			break;

		case NOT_nd:
			return !getValue(root->next);

		case GT_nd:
			return (double) getValue(root->op.left) > getValue(root->op.right);
		
		case LT_nd:
			return (double) getValue(root->op.left) < getValue(root->op.right);

		case GE_nd:
			return (double) getValue(root->op.left) >= getValue(root->op.right);

		case LE_nd:
			return (double) getValue(root->op.left) <= getValue(root->op.right);

		case EQ_nd:
			return (double) getValue(root->op.left) == getValue(root->op.right);

		case NEQ_nd:
			return (double) getValue(root->op.left) != getValue(root->op.right);

		case AND_nd:
			if (!getValue(root->op.left))
				return 0;
			if (!getValue(root->op.right))
				return 0;
			return 1;

		case OR_nd:
			if (getValue(root->op.left))
				return 1;
			if (getValue(root->op.right))
				return 1;
			return 0;

		case VAR_nd:
			if (root->sym->type == UNDEF) {
				fprintf(stderr, "Variable '%s' is undefined.\n", root->sym->name);
				abort();
			}
			return root->sym->val;
		
		case BLTIN_nd:
			return root->sym->ptr(getValue(root->next));

		case FNC_nd:
			{
				Frame *frm = callFunc(root);
				if (retrn) {
					retrn  = false;
					if (frm->retrn.type == NUMBER) {
						return frm->retrn.val;
					} else {
						fprintf(stderr, "Function returns string, can't get value\n");
						abort();
					}
				} else {
					fprintf(stderr, "Nothing returned!\n");
					abort();
				}
				return 0;
			}

		default:
			fprintf(stderr, "Unable to get ast node value\n");
			abort();
	}
	return 0;
}