Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Invariance
- Version 1.0.0
- 2009 Stephan Boyer
- */
- #include "../res/resource.h"
- #include "ocelot.h"
- #include <gl/gl.h>
- #include "calc.h"
- #include "global.h"
- #include "errors.h"
- #include <vector>
- using namespace std;
- void make_graphs(bool silent);
- bool var_exists(std::string name)
- {
- for (int i = 0; i < int(get_var_stack()->size()); i++)
- {
- if (get_var_stack()->at(i).name == name)
- return true;
- }
- return false;
- }
- num get_var(std::string name)
- {
- for (int i = int(get_var_stack()->size())-1; i >= 0; i--)
- {
- if (get_var_stack()->at(i).name == name)
- return get_var_stack()->at(i).x;
- }
- throw_error("unknown variable '"+name+"'", true);
- num x;
- return x;
- }
- void set_var(std::string name, float val)
- {
- var v;
- v.name = name;
- v.x = num::float_to_num(val);
- get_var_stack()->push_back(v);
- make_graphs(true);
- }
- void set_var(std::string name, num val)
- {
- var v;
- v.name = name;
- v.x = val;
- get_var_stack()->push_back(v);
- make_graphs(true);
- }
- struct graph_layer
- {
- node graph_node;
- string graph_var;
- };
- vector <graph_layer> graph_list;
- struct point
- {
- float x, y;
- };
- vector <point> point_list;
- // main window
- bool wnd_open;
- window* wnd;
- void reset()
- {
- // initialize the calculating engine
- graph_list.clear();
- point_list.clear();
- get_var_stack()->clear();
- get_func_stack()->clear();
- (*get_angle_mode()) = ANGLE_RADIANS;
- // create the variables
- var c;
- c.name = "pi";
- c.x = num::string_to_num("3.1415926535897932384626433832795");
- get_var_stack()->push_back(c);
- c.name = "e";
- c.x = num::string_to_num("2.7182818284590452353602874713527");
- get_var_stack()->push_back(c);
- c.name = "xmin";
- c.x = num::string_to_num("-10");
- get_var_stack()->push_back(c);
- c.name = "xmax";
- c.x = num::string_to_num("10");
- get_var_stack()->push_back(c);
- c.name = "ymin";
- c.x = num::string_to_num("-10");
- get_var_stack()->push_back(c);
- c.name = "ymax";
- c.x = num::string_to_num("10");
- get_var_stack()->push_back(c);
- c.name = "gprec";
- c.x = num::string_to_num("0.1");
- get_var_stack()->push_back(c);
- c.name = "cprec";
- c.x = num::string_to_num("0.001");
- get_var_stack()->push_back(c);
- // redraw the window
- make_graphs(true);
- }
- // about window
- bool wnd_about_open;
- window* wnd_about;
- // controls
- int close_about;
- // the message handler for the about box
- void msg_proc_about(message* msg)
- {
- if (msg->msg == MSG_CREATE)
- {
- // create the about graphic
- wnd_about->create_ctrl(CTRL_BITMAP_RESOURCE, "101", 0, 0, 400, 275);
- // create the close button
- close_about = wnd_about->create_ctrl(CTRL_BUTTON, "Close", 152, 283, 96, 24);
- // make the window visible
- wnd_about->set_window_visible(true);
- }
- if (msg->msg == MSG_BUTTONPRESSED && msg->ctrl_id == close_about)
- wnd_about_open = false;
- if (msg->msg == MSG_KEYDOWN)
- {
- if (msg->ctrl_id == OKC_ESCAPE)
- wnd_about_open = false;
- if (msg->ctrl_id == OKC_SPACE)
- wnd_about_open = false;
- if (msg->ctrl_id == OKC_RETURN)
- wnd_about_open = false;
- }
- if (msg->msg == MSG_CLOSE)
- wnd_about_open = false;
- }
- void show_about()
- {
- // create the window and run the message loop
- wnd_about_open = true;
- wnd_about = new window("About Invariance", IDI_ICON1, 400, 315, wnd, &msg_proc_about);
- while (wnd_about_open) wnd_about->update();
- delete wnd_about;
- }
- // reference window
- bool wnd_ref_open;
- window* wnd_ref;
- // controls
- int info_ref;
- int close_ref;
- // the message handler for the reference box
- void msg_proc_ref(message* msg)
- {
- if (msg->msg == MSG_CREATE)
- {
- // create the reference information
- info_ref = wnd_ref->create_ctrl(CTRL_MULTI_EDIT_READONLY,
- "------- Quick User's Guide -------\r\n"
- "\r\n"
- "Simple algebra: 3^5+2sqrt(2pi-1)*e/10.5\r\n"
- "Trig functions: sin(x), cos(x), etc...\r\n"
- "Custom variables: a = 5\r\n"
- "Custom functions: f(x, y) = 3x+5y\r\n"
- "Graphing: y = 8log(x)\r\n"
- "Graphing inverses: x = 4y\r\n"
- "Zoom in/out: zin and zout\r\n"
- "Derivatives: der sin(x), x, 1\r\n"
- " (function, variable of differentiation, point)\r\n"
- "Integrals: int 3x^4, x, 0, 4\r\n"
- " (function, variable of integration, lower limit, upper limit)\r\n"
- "\r\n"
- "------- Reference -------\r\n"
- "\r\n"
- "Expression Axioms:\r\n"
- "\r\n"
- "x - literal value\r\n"
- "x - variable\r\n"
- "f(x, y, z) - function call\r\n"
- "(x) - grouping\r\n"
- "x! - factorial (gamma(x+1))\r\n"
- "x^y - exponent (from left to right)\r\n"
- "x*y, x/y - multiplication/division (from left to right)\r\n"
- "+x, -x - positive/negative\r\n"
- "x+y, x-y - addition/subtraction (from left to right)\r\n"
- "\r\n"
- "Commands:\r\n"
- "\r\n"
- "deg - switch to degree mode\r\n"
- "rad - switch to radian mode\r\n"
- "grad - switch to grad mode\r\n"
- "reset - reset variables to default values\r\n"
- "clear - clear the output window\r\n"
- "wipe - clear the graph window\r\n"
- "exit - quit the program\r\n"
- "x = a - define a variable\r\n"
- "f(x, y, z) = a - define a function\r\n"
- "del x - delete a variable\r\n"
- "del x() - delete a function\r\n"
- "zin - zoom in\r\n"
- "zout - zoom out\r\n"
- "y = f(x), x = f(y) - graph a function\r\n"
- "der f(x), x, a - evaluate the derivative at a point\r\n"
- "int f(x), x, a, b - evaluate the definite integral\r\n"
- "\r\n"
- "Intrinsic Variables:\r\n"
- "\r\n"
- "xmin - the lower x boundry for graphing\r\n"
- "xmax - the upper x boundry for graphing\r\n"
- "ymin - the lower y boundry for graphing\r\n"
- "ymax - the upper y boundry for graphing\r\n"
- "gprec - the step size for graphing\r\n"
- "cprec - the limit value for calculus operations\r\n"
- "e - roughly equal to 2.71828...\r\n"
- "pi - roughly equal to 3.14159...\r\n"
- "\r\n"
- "Intrinsic Functions:\r\n"
- "\r\n"
- "abs(x) - absolute value\r\n"
- "acos(x) - arccosine\r\n"
- "asin(x) - arcsine\r\n"
- "atan(x) - arctangent\r\n"
- "cos(x) - cosine\r\n"
- "cot(x) - cotangent\r\n"
- "csc(x) - cosecant\r\n"
- "ln(x) - natural logarithm\r\n"
- "log(x) - base-10 logarithm\r\n"
- "sec(x) - secant\r\n"
- "sin(x) - sine\r\n"
- "sqrt(x) - square root\r\n"
- "tan(x) - tangent\r\n"
- , 8, 8, 384, 334);
- // create the close button
- close_ref = wnd_ref->create_ctrl(CTRL_BUTTON, "Close", 152, 358, 96, 24);
- // reposition the window
- wnd_ref->set_client_size(400, 400);
- wnd_ref->center_window();
- // make the window visible
- wnd_ref->set_window_visible(true);
- }
- if (msg->msg == MSG_RESIZED)
- {
- // get the width and height of the client area
- int width = wnd_ref->get_client_width();
- int height = wnd_ref->get_client_height();
- // reposition the controls
- wnd_ref->set_ctrl_pos(close_ref, (width-96)/2, height-32);
- wnd_ref->set_ctrl_size(info_ref, width-16, height-48);
- }
- if (msg->msg == MSG_BUTTONPRESSED && msg->ctrl_id == close_ref)
- wnd_ref_open = false;
- if (msg->msg == MSG_KEYDOWN)
- {
- if (msg->ctrl_id == OKC_ESCAPE)
- wnd_ref_open = false;
- if (msg->ctrl_id == OKC_SPACE)
- wnd_ref_open = false;
- if (msg->ctrl_id == OKC_RETURN)
- wnd_ref_open = false;
- }
- if (msg->msg == MSG_CLOSE)
- wnd_ref_open = false;
- }
- void show_ref()
- {
- // create the window and run the message loop
- wnd_ref_open = true;
- wnd_ref = new window("Invariance Reference", IDI_ICON1, 0, 0, wnd, &msg_proc_ref);
- while (wnd_ref_open) wnd_ref->update();
- delete wnd_ref;
- }
- // fonts
- HFONT font;
- // hotkeys
- int hot_f1;
- // controls
- int input;
- int output;
- int graph;
- // menu items
- int menu_file_exit;
- int menu_help_ref;
- int menu_help_about;
- // the log text
- string log_text;
- const int log_max_size = 1000;
- void log(string str)
- {
- if (log_text == "")
- log_text = str;
- else
- log_text = str+"\r\n"+log_text;
- if (log_text.size() > log_max_size)
- log_text = log_text.substr(0, log_max_size);
- wnd->set_ctrl_text(output, log_text);
- }
- void clear_log()
- {
- log_text = "";
- wnd->set_ctrl_text(output, log_text);
- }
- void make_graphs(bool silent)
- {
- // ignore nonfatal errors during graphing
- respond_to_nonfatals(false);
- point_list.clear();
- try
- {
- // fetch the variables
- float xmin = num::num_to_float(get_var("xmin"));
- float ymin = num::num_to_float(get_var("ymin"));
- float xmax = num::num_to_float(get_var("xmax"));
- float ymax = num::num_to_float(get_var("ymax"));
- float prec = num::num_to_float(get_var("gprec"));
- if (num::num_eq(get_var("xmin"), get_var("xmax")))
- throw_error("xmax cannot equal xmin", true);
- if (num::num_eq(get_var("ymin"), get_var("ymax")))
- throw_error("ymax cannot equal ymin", true);
- if (prec <= 0.0f)
- throw_error("invalid value for gprec", true);
- for (int i = 0; i < int(graph_list.size()); i++)
- {
- try
- {
- // create the independent variable
- if (graph_list[i].graph_var == "x")
- {
- // the independent variable is y
- var v;
- v.name = "y";
- get_var_stack()->push_back(v);
- }
- else
- {
- // the independent variable is x
- var v;
- v.name = "x";
- get_var_stack()->push_back(v);
- }
- // graph
- if (graph_list[i].graph_var == "x")
- {
- point p;
- point p2;
- point p3; // used for distance checking
- bool first = true;
- if (ymin < ymax)
- {
- for (p.y = ymin-prec; p.y <= ymax+prec; p.y += prec)
- {
- get_var_stack()->at(get_var_stack()->size()-1).x = num::float_to_num(p.y);
- p.x = num::num_to_float(graph_list[i].graph_node.eval());
- // transform to screen coordinates [0-1]
- p2.x = (p.x-xmin)/(xmax-xmin);
- p2.y = (p.y-ymin)/(ymax-ymin);
- // calculate the squared distance
- float d = 0.0f;
- if (!first)
- d = (p2.x-p3.x)*(p2.x-p3.x)+(p2.y-p3.y)*(p2.y-p3.y);
- p3.x = p2.x;
- p3.y = p2.y;
- if (!first)
- {
- if (d < 1.0f)
- point_list.push_back(p2);
- else
- point_list.pop_back();
- }
- point_list.push_back(p2);
- first = false;
- }
- }
- else
- {
- for (p.y = ymin+prec; p.y >= ymax-prec; p.y -= prec)
- {
- get_var_stack()->at(get_var_stack()->size()-1).x = num::float_to_num(p.y);
- p.x = num::num_to_float(graph_list[i].graph_node.eval());
- // transform to screen coordinates [0-1]
- p2.x = (p.x-xmin)/(xmax-xmin);
- p2.y = (p.y-ymin)/(ymax-ymin);
- // calculate the squared distance
- float d = 0.0f;
- if (!first)
- d = (p2.x-p3.x)*(p2.x-p3.x)+(p2.y-p3.y)*(p2.y-p3.y);
- p3.x = p2.x;
- p3.y = p2.y;
- if (!first)
- {
- if (d < 1.0f)
- point_list.push_back(p2);
- else
- point_list.pop_back();
- }
- point_list.push_back(p2);
- first = false;
- }
- }
- point_list.pop_back();
- }
- else
- {
- point p;
- point p2;
- point p3; // used for distance checking
- bool first = true;
- if (xmin < xmax)
- {
- for (p.x = xmin-prec; p.x <= xmax+prec; p.x += prec)
- {
- get_var_stack()->at(get_var_stack()->size()-1).x = num::float_to_num(p.x);
- p.y = num::num_to_float(graph_list[i].graph_node.eval());
- // transform to screen coordinates [0-1]
- p2.x = (p.x-xmin)/(xmax-xmin);
- p2.y = (p.y-ymin)/(ymax-ymin);
- // calculate the squared distance
- float d = 0.0f;
- if (!first)
- d = (p2.x-p3.x)*(p2.x-p3.x)+(p2.y-p3.y)*(p2.y-p3.y);
- p3.x = p2.x;
- p3.y = p2.y;
- if (!first)
- {
- if (d < 1.0f)
- point_list.push_back(p2);
- else
- point_list.pop_back();
- }
- point_list.push_back(p2);
- first = false;
- }
- }
- else
- {
- for (p.x = xmin+prec; p.x >= xmax-prec; p.x -= prec)
- {
- get_var_stack()->at(get_var_stack()->size()-1).x = num::float_to_num(p.x);
- p.y = num::num_to_float(graph_list[i].graph_node.eval());
- // transform to screen coordinates [0-1]
- p2.x = (p.x-xmin)/(xmax-xmin);
- p2.y = (p.y-ymin)/(ymax-ymin);
- // calculate the squared distance
- float d = 0.0f;
- if (!first)
- d = (p2.x-p3.x)*(p2.x-p3.x)+(p2.y-p3.y)*(p2.y-p3.y);
- p3.x = p2.x;
- p3.y = p2.y;
- if (!first)
- {
- if (d < 1.0f)
- point_list.push_back(p2);
- else
- point_list.pop_back();
- }
- point_list.push_back(p2);
- first = false;
- }
- }
- point_list.pop_back();
- }
- // destroy the independent variable
- get_var_stack()->pop_back();
- }
- catch (string e)
- {
- if (!silent)
- log(e);
- }
- }
- // graph the axes
- point p1;
- point p2;
- p1.x = 0.0f;
- p1.y = 0.0f;
- p2.x = 1.0f;
- p2.y = 0.0f;
- p1.y = (p1.y-ymin)/(ymax-ymin);
- p2.y = (p2.y-ymin)/(ymax-ymin);
- point_list.push_back(p1);
- point_list.push_back(p2);
- p1.x = 0.0f;
- p1.y = 0.0f;
- p2.x = 0.0f;
- p2.y = 1.0f;
- p1.x = (p1.x-xmin)/(xmax-xmin);
- p2.x = (p2.x-xmin)/(xmax-xmin);
- point_list.push_back(p1);
- point_list.push_back(p2);
- }
- catch (string e)
- {
- if (!silent)
- log(e);
- }
- // redraw the window
- wnd->redraw();
- // re-enable the nonfatal error system
- respond_to_nonfatals(true);
- }
- // the main message handler
- void msg_proc(message* msg)
- {
- if (msg->msg == MSG_CREATE)
- {
- // activate minimum window size
- wnd->set_client_min_size(420, 200);
- // set up the menu
- wnd->menu_push("File");
- menu_file_exit = wnd->menu_item("Exit", true, false);
- wnd->menu_pop();
- wnd->menu_push("Help");
- menu_help_ref = wnd->menu_item("View Reference\tF1", true, false);
- wnd->menu_separator();
- menu_help_about = wnd->menu_item("About Invariance", true, false);
- wnd->menu_pop();
- // set up the statusbar
- wnd->set_statusbar_enabled(true, "Ready");
- // create the "Input" text
- wnd->create_ctrl(CTRL_TEXT, "Input:", 8, 4, 200, 20);
- // create the "Output" text
- wnd->create_ctrl(CTRL_TEXT, "Output:", 8, 52, 200, 20);
- // create the "Graph" text
- wnd->create_ctrl(CTRL_TEXT, "Graph:", 216, 4, 200, 20);
- // create the input box
- input = wnd->create_ctrl(CTRL_SINGLE_EDIT, "", 8, 24, 200, 24);
- // create the output box
- output = wnd->create_ctrl(CTRL_MULTI_EDIT_READONLY, "", 8, 72, 200, 120);
- // create the graph box
- graph = wnd->create_ctrl(CTRL_OPENGL, "", 216, 24, 200, 168);
- // set the font of the input and output boxes
- HDC hdc = GetDC(wnd->get_handle());
- font = CreateFont(-MulDiv(10, GetDeviceCaps(hdc, LOGPIXELSY), 72), 0, 0, 0, FW_NORMAL, false, false, false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Courier New");
- ReleaseDC(wnd->get_handle(), hdc);
- SendMessage(wnd->get_ctrl_handle(input), WM_SETFONT, (WPARAM)font, (LPARAM)false);
- SendMessage(wnd->get_ctrl_handle(output), WM_SETFONT, (WPARAM)font, (LPARAM)false);
- // create the hotkeys
- hot_f1 = wnd->create_hotkey(OKC_F1, false, false, false);
- // make the window visible
- wnd->set_window_visible(true);
- // grab the focus of the input box
- wnd->grab_ctrl_focus(input);
- // initialize the calculating engine
- reset();
- respond_to_nonfatals(true);
- make_graphs(true);
- }
- if (msg->msg == MSG_HOTKEY)
- {
- if (msg->ctrl_id == hot_f1)
- show_ref();
- }
- if (msg->msg == MSG_RESIZED)
- {
- // get the width and height of the client area
- int width = wnd->get_client_width();
- int height = wnd->get_client_height();
- // reposition the controls
- wnd->set_ctrl_size(output, 200, height-80);
- wnd->set_ctrl_size(graph, width-224, height-32);
- // grab the focus of the input box
- wnd->grab_ctrl_focus(input);
- }
- if (msg->msg == MSG_REDRAW)
- {
- // get the width and height of the client area
- int width = wnd->get_client_width();
- int height = wnd->get_client_height();
- // get the width and height of the control
- int graph_width = width-224;
- int graph_height = height-32;
- // begin rendering on a black graph
- wnd->ctrl_begin(graph, 0.0f, 0.0f, 0.0f);
- // set the viewport
- glViewport(0, 0, graph_width, graph_height);
- // set up the projection matrices
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f);
- // set the color
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- // render stuff
- glBegin(GL_LINES);
- for (int i = 0; i < int(point_list.size()); i++)
- glVertex2f(point_list[i].x, 1.0f-point_list[i].y);
- glEnd();
- // finish rendering
- wnd->ctrl_end();
- }
- if (msg->msg == MSG_MENU)
- {
- // the user wants to quit
- if (msg->ctrl_id == menu_file_exit)
- wnd_open = false;
- // the user wants to learn about the program
- if (msg->ctrl_id == menu_help_about)
- show_about();
- // the user wants to learn about the syntax
- if (msg->ctrl_id == menu_help_ref)
- show_ref();
- }
- if (msg->msg == MSG_ACTIVATED)
- {
- // grab the focus of the input box
- wnd->grab_ctrl_focus(input);
- }
- if (msg->msg == MSG_CLOSE)
- wnd_open = false;
- if (msg->msg == MSG_DESTROY)
- DeleteObject(font);
- if (msg->msg == MSG_EDITRETURNED)
- {
- if (msg->ctrl_id == input)
- {
- log("");
- string str = wnd->get_ctrl_text(input);
- try
- {
- vector <token> token_list = tokenize(str);
- bool go_on = true;
- if (token_list.size() == 1)
- {
- if (token_list[0].type == TOK_NAME && token_list[0].text == "rad")
- {
- go_on = false;
- (*get_angle_mode()) = ANGLE_RADIANS;
- log("radians mode");
- log("> "+str);
- make_graphs(true);
- }
- if (token_list[0].type == TOK_NAME && token_list[0].text == "deg")
- {
- go_on = false;
- (*get_angle_mode()) = ANGLE_DEGREES;
- log("degrees mode");
- log("> "+str);
- make_graphs(true);
- }
- if (token_list[0].type == TOK_NAME && token_list[0].text == "grad")
- {
- go_on = false;
- (*get_angle_mode()) = ANGLE_GRADS;
- log("grads mode");
- log("> "+str);
- make_graphs(true);
- }
- if (token_list[0].type == TOK_NAME && token_list[0].text == "zin")
- {
- go_on = false;
- float xmin = num::num_to_float(get_var("xmin"));
- float ymin = num::num_to_float(get_var("ymin"));
- float xmax = num::num_to_float(get_var("xmax"));
- float ymax = num::num_to_float(get_var("ymax"));
- float cx = (xmin+xmax)/2.0f;
- float cy = (ymin+ymax)/2.0f;
- xmin += (cx-xmin)/2.0f;
- ymin += (cy-ymin)/2.0f;
- xmax += (cx-xmax)/2.0f;
- ymax += (cy-ymax)/2.0f;
- set_var("xmin", xmin);
- set_var("ymin", ymin);
- set_var("xmax", xmax);
- set_var("ymax", ymax);
- log("zoomed in");
- log("> "+str);
- }
- if (token_list[0].type == TOK_NAME && token_list[0].text == "zout")
- {
- go_on = false;
- float xmin = num::num_to_float(get_var("xmin"));
- float ymin = num::num_to_float(get_var("ymin"));
- float xmax = num::num_to_float(get_var("xmax"));
- float ymax = num::num_to_float(get_var("ymax"));
- float cx = (xmin+xmax)/2.0f;
- float cy = (ymin+ymax)/2.0f;
- xmin -= (cx-xmin)/2.0f;
- ymin -= (cy-ymin)/2.0f;
- xmax -= (cx-xmax)/2.0f;
- ymax -= (cy-ymax)/2.0f;
- set_var("xmin", xmin);
- set_var("ymin", ymin);
- set_var("xmax", xmax);
- set_var("ymax", ymax);
- log("zoomed out");
- log("> "+str);
- }
- if (token_list[0].type == TOK_NAME && token_list[0].text == "reset")
- {
- go_on = false;
- reset();
- log("system reset");
- log("> "+str);
- }
- if (token_list[0].type == TOK_NAME && token_list[0].text == "clear")
- {
- go_on = false;
- clear_log();
- }
- if (token_list[0].type == TOK_NAME && token_list[0].text == "wipe")
- {
- go_on = false;
- graph_list.clear();
- point_list.clear();
- make_graphs(true);
- log("graph wiped");
- log("> "+str);
- }
- if (token_list[0].type == TOK_NAME && token_list[0].text == "exit")
- {
- go_on = false;
- wnd_open = false;
- }
- }
- if (token_list.size() > 1)
- {
- if (token_list[0].type == TOK_NAME && token_list[1].type == TOK_EQUAL)
- {
- if (token_list[0].text != "x" && token_list[0].text != "y")
- {
- go_on = false;
- var v;
- v.name = token_list[0].text;
- vector <token> token_list1;
- for (int j = 2; j < int(token_list.size()); j++)
- token_list1.push_back(token_list[j]);
- node n1(token_list1);
- v.x = n1.eval();
- get_var_stack()->push_back(v);
- log(num::num_to_string(v.x));
- log("> "+str);
- make_graphs(true);
- }
- }
- if (token_list[0].type == TOK_NAME && token_list[0].text == "der")
- {
- go_on = false;
- vector <token> token_list1;
- int scope = 0;
- int comma_pos = -1;
- for (int j = 1; j < int(token_list.size()); j++)
- {
- if (token_list[j].type == TOK_BEGINPAREN)
- scope--;
- if (token_list[j].type == TOK_ENDPAREN)
- scope++;
- if (scope == 0 && token_list[j].type == TOK_COMMA)
- {
- comma_pos = j;
- break;
- }
- token_list1.push_back(token_list[j]);
- }
- if (comma_pos == -1)
- throw_error("missing ','", true);
- node n1(token_list1);
- if (int(token_list.size()) <= comma_pos+1)
- throw_error("missing variable name", true);
- if (token_list[comma_pos+1].type != TOK_NAME)
- throw_error("missing variable name", true);
- string varname = token_list[comma_pos+1].text;
- if (int(token_list.size()) <= comma_pos+2)
- throw_error("missing ','", true);
- if (token_list[comma_pos+2].type != TOK_COMMA)
- throw_error("missing ','", true);
- vector <token> token_list2;
- for (int j = comma_pos+3; j < int(token_list.size()); j++)
- token_list2.push_back(token_list[j]);
- node n2(token_list2);
- num inc(get_var("cprec"));
- if (num::num_lteq(inc, num::string_to_num("0")))
- throw_error("invalid value for cprec", true);
- num x1(n2.eval());
- num x2(num::num_add(x1, inc));
- set_var(varname, x1);
- num y1(n1.eval());
- get_var_stack()->pop_back();
- set_var(varname, x2);
- num y2(n1.eval());
- get_var_stack()->pop_back();
- log(num::num_to_string(num::num_div(num::num_sub(y2, y1), inc)));
- log("> "+str);
- }
- if (token_list[0].type == TOK_NAME && token_list[0].text == "int")
- {
- go_on = false;
- vector <token> token_list1;
- int scope = 0;
- int comma_pos = -1;
- for (int j = 1; j < int(token_list.size()); j++)
- {
- if (token_list[j].type == TOK_BEGINPAREN)
- scope--;
- if (token_list[j].type == TOK_ENDPAREN)
- scope++;
- if (scope == 0 && token_list[j].type == TOK_COMMA)
- {
- comma_pos = j;
- break;
- }
- token_list1.push_back(token_list[j]);
- }
- if (comma_pos == -1)
- throw_error("missing ','", true);
- node n1(token_list1);
- if (int(token_list.size()) <= comma_pos+1)
- throw_error("missing variable name", true);
- if (token_list[comma_pos+1].type != TOK_NAME)
- throw_error("missing variable name", true);
- string varname = token_list[comma_pos+1].text;
- if (int(token_list.size()) <= comma_pos+2)
- throw_error("missing ','", true);
- if (token_list[comma_pos+2].type != TOK_COMMA)
- throw_error("missing ','", true);
- vector <token> token_list2;
- scope = 0;
- int start_pos = comma_pos+3;
- comma_pos = -1;
- for (int j = start_pos; j < int(token_list.size()); j++)
- {
- if (token_list[j].type == TOK_BEGINPAREN)
- scope--;
- if (token_list[j].type == TOK_ENDPAREN)
- scope++;
- if (scope == 0 && token_list[j].type == TOK_COMMA)
- {
- comma_pos = j;
- break;
- }
- token_list2.push_back(token_list[j]);
- }
- if (comma_pos == -1)
- throw_error("missing ','", true);
- node n2(token_list2);
- vector <token> token_list3;
- for (int j = comma_pos+1; j < int(token_list.size()); j++)
- token_list3.push_back(token_list[j]);
- node n3(token_list3);
- num two(num::string_to_num("2"));
- num sum(num::string_to_num("0"));
- num inc(get_var("cprec"));
- if (num::num_lteq(inc, num::string_to_num("0")))
- throw_error("invalid value for cprec", true);
- num lower(n2.eval());
- num upper(n3.eval());
- set_var(varname, lower);
- bool first = true;
- num last_val;
- if (num::num_lteq(lower, upper))
- {
- for (num x(lower); num::num_lteq(x, upper); x = num::num_add(x, inc))
- {
- get_var_stack()->at(get_var_stack()->size()-1).x = x;
- if (first)
- sum = num::num_add(sum, n1.eval());
- else
- {
- last_val = n1.eval();
- sum = num::num_add(sum, num::num_mul(last_val, two));
- }
- first = false;
- }
- get_var_stack()->pop_back();
- num interval(num::num_sub(upper, lower));
- sum = num::num_sub(sum, last_val);
- sum = num::num_div(sum, num::num_mul(two, num::num_div(interval, inc)));
- sum = num::num_mul(sum, interval);
- }
- else
- {
- for (num x(lower); num::num_gteq(x, upper); x = num::num_sub(x, inc))
- {
- get_var_stack()->at(get_var_stack()->size()-1).x = x;
- if (first)
- sum = num::num_add(sum, n1.eval());
- else
- {
- last_val = n1.eval();
- sum = num::num_add(sum, num::num_mul(last_val, two));
- }
- first = false;
- }
- get_var_stack()->pop_back();
- num interval(num::num_sub(upper, lower));
- sum = num::num_sub(sum, last_val);
- sum = num::num_div(sum, num::num_mul(two, num::num_div(interval, inc)));
- sum = num::num_mul(sum, interval);
- sum = num::num_neg(sum);
- }
- log(num::num_to_string(sum));
- log("> "+str);
- }
- if (token_list[0].type == TOK_NAME && token_list[1].type == TOK_BEGINPAREN)
- {
- bool found = false;
- int locus = -1;
- for (int j = 2; j < int(token_list.size()); j++)
- {
- if (token_list[j].type == TOK_EQUAL)
- {
- found = true;
- locus = j;
- break;
- }
- }
- if (found)
- {
- go_on = false;
- func f;
- f.name = token_list[0].text;
- bool expecting_comma = false;
- bool success = false;
- for (int j = 2; j < int(token_list.size()); j++)
- {
- if (expecting_comma)
- {
- if (token_list[j].type == TOK_ENDPAREN)
- {
- success = true;
- break;
- }
- if (token_list[j].type != TOK_COMMA)
- throw_error("missing ','", true);
- }
- else
- {
- if (j == 2 && token_list[j].type == TOK_ENDPAREN)
- {
- success = true;
- break;
- }
- if (token_list[j].type == TOK_NAME)
- f.args.push_back(token_list[j].text);
- else
- throw_error("missing argument name", true);
- }
- expecting_comma = !expecting_comma;
- }
- if (!success)
- throw_error("missing ')'", true);
- vector <token> token_list1;
- for (int j = locus+1; j < int(token_list.size()); j++)
- token_list1.push_back(token_list[j]);
- node n1(token_list1);
- f.x = n1;
- get_func_stack()->push_back(f);
- log("> "+str);
- }
- }
- if (token_list.size() == 2 && token_list[0].type == TOK_NAME && token_list[1].type == TOK_NAME)
- {
- if (token_list[0].text == "del")
- {
- go_on = false;
- bool found = false;
- for (int i = int(get_var_stack()->size())-1; i >= 0; i--)
- {
- if (get_var_stack()->at(i).name == token_list[1].text)
- {
- found = true;
- get_var_stack()->erase(get_var_stack()->begin()+i);
- break;
- }
- }
- if (found)
- {
- log("variable deleted");
- log("> "+str);
- }
- else
- throw_error("unknown variable: "+token_list[1].text, true);
- }
- }
- if (token_list.size() == 4 && token_list[0].type == TOK_NAME && token_list[1].type == TOK_NAME && token_list[2].type == TOK_BEGINPAREN && token_list[3].type == TOK_ENDPAREN)
- {
- if (token_list[0].text == "del")
- {
- go_on = false;
- bool found = false;
- for (int i = int(get_func_stack()->size())-1; i >= 0; i--)
- {
- if (get_func_stack()->at(i).name == token_list[1].text)
- {
- found = true;
- get_func_stack()->erase(get_func_stack()->begin()+i);
- break;
- }
- }
- if (found)
- {
- log("function deleted");
- log("> "+str);
- }
- else
- throw_error("unknown function: "+token_list[1].text, true);
- }
- }
- if (token_list[0].type == TOK_NAME && token_list[1].type == TOK_EQUAL)
- {
- // ensure that this is an x or y plot
- if (token_list[0].text == "x" || token_list[0].text == "y")
- {
- go_on = false;
- graph_layer g;
- g.graph_var = token_list[0].text;
- // get the expression
- vector <token> token_list1;
- for (int j = 2; j < int(token_list.size()); j++)
- token_list1.push_back(token_list[j]);
- g.graph_node.from_tokens(token_list1);
- // graph
- graph_list.push_back(g);
- make_graphs(false);
- // output the original command
- log("> "+str);
- }
- }
- }
- if (go_on)
- {
- node n(token_list);
- log(num::num_to_string(n.eval()));
- log("> "+str);
- }
- }
- catch (string e)
- {
- log(e);
- log("> "+str);
- respond_to_nonfatals(true);
- }
- wnd->set_ctrl_text(input, "");
- }
- }
- }
- int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil)
- {
- // create the window and run the message loop
- wnd_open = true;
- wnd = new window("Invariance", IDI_ICON1, 0, 0, NULL, &msg_proc);
- while (wnd_open) wnd->update();
- delete wnd;
- return 0;
- }
Add Comment
Please, Sign In to add comment