[
  {
    "path": ".gitignore",
    "content": "\n# object files\n*.o\n\n# codeblocks project files\n*.layout\n*.depend\n*.cscope_file_list\n\n# Valgrind\n*cachegrind.out*\n*ValgrindOut.xml\n\n# executables\nPineconeDbg\nPineconeBin\nPinecone\npinecone\n\n#KDevelop\n.kdev4\n\n# stupid OSX stuff\n*.DS_Store\n\n# repl temp file\nrepl/tmp.pn\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2017 Sophie Winter\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "# I'm totally aware how shitty this makefile is\n# I use the IDE Code::Blocks; this is only for people who don't have that\n# I'll write a proper makefile at some point\n\nbuild:\n\tg++ -Wall -std=c++11 -O2 src/*.cpp src/Actions/*.cpp src/utils/*.cpp -o pinecone\n"
  },
  {
    "path": "_config.yml",
    "content": "theme: jekyll-theme-hacker"
  },
  {
    "path": "changelog.md",
    "content": "# Pinecone Changelog\nThis file documents all major changes to the Pinecone langauge.\nEvery new version gets a number of minor bug fixes, so they are not included\n\n### v0.5.1 (April 20, 2017)\n\n* Fixed silent error when file fails to load\n* Fixed known bug with functions that take one named argument\n* Fixed known bug that prevented `?` being useed in a ternary expression\n* Improved output of testing script\n* Internal codebase cleanup\n\n## v0.5.0 (April 14, 2017)\n\n* Made `&&` and `||` use short circuiting\n* Improved testing system\n* Added support for Windows\n* __Added Whatev type__ for compile time dynamic typing and implicit function return type\n\n## v0.4.0 (Mar 26, 2017)\n\n* Added command line options for transpileing\n* __Fully implemented transpiler to C++__\n* Disabled implicit conversion between two structs (if neither is an anonymous tuple)\n* Added `!=` operator\n* Wrote more example programs including a brainfuck interpreter\n* Fixed bug that prevented accessing multiple layers of structures with dot ('struct.data.func: arg' now works)\n* Added a wide range of unit tests and integration tests\n* Added escape character support to Strings\n* Added support for running shell commands\n* Added explicit conversion of primitive types to Strings\n* Improved tutorial navigation\n\n## v0.3.0 (Jan 18, 2017)\n\n* __Added string literal support__\n* Added various functions and operators for strings\n* Fixed globals\n\n### v0.2.1 (Jan 16, 2017)\n\n* Fixed bug introduced in v0.2.0 with functions\n* Fixed bug with line numbers in error messages\n\n## v0.2.0 (Jan 16, 2017)\n\n* Added file import feature\n* Flipped open and close block comments\n* Removed debugging info by default\n* Added command line args\n\n## v0.1.0 (Jan 15, 2017)\n\n* __Created Pinecone__\n\n## v0.0.0\n\n* Pinecone did not exist\n"
  },
  {
    "path": "codeblocks/Pinecone.cbp",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n<CodeBlocks_project_file>\n\t<FileVersion major=\"1\" minor=\"6\" />\n\t<Project>\n\t\t<Option title=\"Pinecone\" />\n\t\t<Option pch_mode=\"2\" />\n\t\t<Option default_target=\"Release\" />\n\t\t<Option compiler=\"gcc\" />\n\t\t<Build>\n\t\t\t<Target title=\"Debug_R\">\n\t\t\t\t<Option output=\"../pinecone\" prefix_auto=\"1\" extension_auto=\"1\" />\n\t\t\t\t<Option working_dir=\"../\" />\n\t\t\t\t<Option type=\"1\" />\n\t\t\t\t<Option compiler=\"gcc\" />\n\t\t\t\t<Option parameters=\"other/pinecone.pn -d -r\" />\n\t\t\t\t<Compiler>\n\t\t\t\t\t<Add option=\"-g\" />\n\t\t\t\t</Compiler>\n\t\t\t</Target>\n\t\t\t<Target title=\"Debug_E\">\n\t\t\t\t<Option output=\"../pinecone\" prefix_auto=\"1\" extension_auto=\"1\" />\n\t\t\t\t<Option working_dir=\"../\" />\n\t\t\t\t<Option type=\"1\" />\n\t\t\t\t<Option compiler=\"gcc\" />\n\t\t\t\t<Option parameters=\"other/pinecone.pn -d -e\" />\n\t\t\t\t<Compiler>\n\t\t\t\t\t<Add option=\"-g\" />\n\t\t\t\t</Compiler>\n\t\t\t</Target>\n\t\t\t<Target title=\"Test\">\n\t\t\t\t<Option output=\"../pinecone\" prefix_auto=\"1\" extension_auto=\"1\" />\n\t\t\t\t<Option working_dir=\"../\" />\n\t\t\t\t<Option type=\"1\" />\n\t\t\t\t<Option compiler=\"gcc\" />\n\t\t\t\t<Option parameters=\"tests/run_tests.pn\" />\n\t\t\t\t<Compiler>\n\t\t\t\t\t<Add option=\"-g\" />\n\t\t\t\t</Compiler>\n\t\t\t</Target>\n\t\t\t<Target title=\"Release\">\n\t\t\t\t<Option output=\"../pinecone\" prefix_auto=\"1\" extension_auto=\"1\" />\n\t\t\t\t<Option working_dir=\"../\" />\n\t\t\t\t<Option type=\"1\" />\n\t\t\t\t<Option compiler=\"gcc\" />\n\t\t\t\t<Option parameters=\"-v\" />\n\t\t\t\t<Compiler>\n\t\t\t\t\t<Add option=\"-O2\" />\n\t\t\t\t</Compiler>\n\t\t\t\t<Linker>\n\t\t\t\t\t<Add option=\"-s\" />\n\t\t\t\t</Linker>\n\t\t\t</Target>\n\t\t</Build>\n\t\t<Compiler>\n\t\t\t<Add option=\"-O\" />\n\t\t\t<Add option=\"-Wall\" />\n\t\t\t<Add option=\"-std=c++11\" />\n\t\t\t<Add option=\"-fexceptions\" />\n\t\t</Compiler>\n\t\t<Unit filename=\"../h/Action.h\" />\n\t\t<Unit filename=\"../h/AllOperators.h\" />\n\t\t<Unit filename=\"../h/AstNode.h\" />\n\t\t<Unit filename=\"../h/CppProgram.h\" />\n\t\t<Unit filename=\"../h/ErrorHandler.h\" />\n\t\t<Unit filename=\"../h/Namespace.h\" />\n\t\t<Unit filename=\"../h/Operator.h\" />\n\t\t<Unit filename=\"../h/PineconeProgram.h\" />\n\t\t<Unit filename=\"../h/SourceFile.h\" />\n\t\t<Unit filename=\"../h/StackFrame.h\" />\n\t\t<Unit filename=\"../h/Token.h\" />\n\t\t<Unit filename=\"../h/Type.h\" />\n\t\t<Unit filename=\"../h/VERSION.h\" />\n\t\t<Unit filename=\"../h/msclStringFuncs.h\" />\n\t\t<Unit filename=\"../h/utils/fileUtils.h\" />\n\t\t<Unit filename=\"../h/utils/stringArray.h\" />\n\t\t<Unit filename=\"../h/utils/stringDrawing.h\" />\n\t\t<Unit filename=\"../h/utils/stringNumConversion.h\" />\n\t\t<Unit filename=\"../h/utils/stringUtils.h\" />\n\t\t<Unit filename=\"../other/pinecone.pn\" />\n\t\t<Unit filename=\"../other/pinecone_concept.txt\" />\n\t\t<Unit filename=\"../readme.md\" />\n\t\t<Unit filename=\"../src/Actions/Action.cpp\" />\n\t\t<Unit filename=\"../src/Actions/BoolOpAction.cpp\" />\n\t\t<Unit filename=\"../src/Actions/BranchAction.cpp\" />\n\t\t<Unit filename=\"../src/Actions/FunctionAction.cpp\" />\n\t\t<Unit filename=\"../src/Actions/IfAction.cpp\" />\n\t\t<Unit filename=\"../src/Actions/ListAction.cpp\" />\n\t\t<Unit filename=\"../src/Actions/LoopAction.cpp\" />\n\t\t<Unit filename=\"../src/Actions/MakeTupleAction.cpp\" />\n\t\t<Unit filename=\"../src/Actions/TypeAction.cpp\" />\n\t\t<Unit filename=\"../src/Actions/VarAction.cpp\" />\n\t\t<Unit filename=\"../src/AllOperators.cpp\" />\n\t\t<Unit filename=\"../src/AstNode.cpp\" />\n\t\t<Unit filename=\"../src/CppProgram.cpp\" />\n\t\t<Unit filename=\"../src/ErrorHandler.cpp\" />\n\t\t<Unit filename=\"../src/Lexer.cpp\" />\n\t\t<Unit filename=\"../src/Namespace.cpp\" />\n\t\t<Unit filename=\"../src/Parser.cpp\" />\n\t\t<Unit filename=\"../src/PineconeProgram.cpp\" />\n\t\t<Unit filename=\"../src/PineconeStdLib.cpp\" />\n\t\t<Unit filename=\"../src/ResolveLiteral.cpp\" />\n\t\t<Unit filename=\"../src/SourceFile.cpp\" />\n\t\t<Unit filename=\"../src/StackFrame.cpp\" />\n\t\t<Unit filename=\"../src/Token.cpp\" />\n\t\t<Unit filename=\"../src/Type.cpp\" />\n\t\t<Unit filename=\"../src/main.cpp\" />\n\t\t<Unit filename=\"../src/msclStringFuncs.cpp\" />\n\t\t<Unit filename=\"../src/utils/fileUtils.cpp\" />\n\t\t<Unit filename=\"../src/utils/stringArray.cpp\" />\n\t\t<Unit filename=\"../src/utils/stringDrawing.cpp\" />\n\t\t<Unit filename=\"../src/utils/stringNumConversion.cpp\" />\n\t\t<Unit filename=\"../src/utils/stringUtils.cpp\" />\n\t\t<Unit filename=\"../tests/run_tests.pn\" />\n\t\t<Unit filename=\"../tutorials/0_setting_up.md\" />\n\t\t<Unit filename=\"../tutorials/1_basic_concepts.md\" />\n\t\t<Unit filename=\"../tutorials/2_control_flow.md\" />\n\t\t<Unit filename=\"../tutorials/3_strings_and_input.md\" />\n\t\t<Unit filename=\"../tutorials/4_structures_and_functions.md\" />\n\t\t<Unit filename=\"../tutorials/5_transpiling_to_cpp.md\" />\n\t\t<Unit filename=\"../tutorials/6_temporary_hacks.md\" />\n\t\t<Unit filename=\"../tutorials/index.md\" />\n\t\t<Extensions>\n\t\t\t<code_completion />\n\t\t\t<envvars />\n\t\t\t<debugger />\n\t\t\t<lib_finder disable_auto=\"1\" />\n\t\t</Extensions>\n\t</Project>\n</CodeBlocks_project_file>\n"
  },
  {
    "path": "codeblocks/readme.md",
    "content": "I use Code::Blocks as my primary IDE, and so it is convenient for me to keep a Code::Blocks project in this repo. All Code::Blocks specific stuff should be in this directory.\n"
  },
  {
    "path": "examples/brainfuck.pn",
    "content": "\n//\nThis is an interpreter for the esoteric programming language brainfuck\n\\\\\n\ndata: IntArray: 40000\noffset: 0\nerror: fls\ninText: \"\"\n\nj: 0 | j<data.len | j: j+1 @\n\tdata.set: j, 0\n\ncode: \"enter your brainfuck code: \".input\n#code: \"++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.\"\n\nprocessSection: code, 0, tru\n\nerror ?\n(\n\tprint: \"program aborted due to error\"\n\tprint: \"position at exit:\"\n\tprint: offset\n)\n\n# runs a loop of bf code, returns when done \nprocessSection :: {src: String, start: Int, isTopLevel: Bool}: (\n\t\n\ti: (in.start)\n\tquit: fls\n\t\n\t!quit && !error @ (\n\t\tc: in.src.sub: i, i+1\n\t\t\n\t\tc = \"<\" ? (\n\t\t\toffset: offset-1\n\t\t\toffset < 0 ? (\n\t\t\t\tprint: \"you went too far left\"\n\t\t\t\terror: tru\n\t\t\t)\n\t\t)\n\t\t| c = \">\" ? (\n\t\t\toffset: offset+1\n\t\t\toffset >= data.len ? (\n\t\t\t\tprint: \"you went too far right\"\n\t\t\t\terror: tru\n\t\t\t)\n\t\t)\n\t\t| c = \"+\" ? (\n\t\t\tdata.set: offset, (data.get: offset)+1\n\t\t)\n\t\t| c = \"-\" ? (\n\t\t\tdata.set: offset, (data.get: offset)-1\n\t\t)\n\t\t| c = \".\" ? (\n\t\t\tprintc: data.get: offset\n\t\t)\n\t\t| c = \",\" ? (\n\t\t\tdata.set: offset, inputc\n\t\t)\n\t\t| c = \"[\" ? (\n\t\t\tprocessSection: in.src, i+1, fls\n\t\t\ti: skipBrace: in.src, i\n\t\t)\n\t\t| c = \"]\" ? (\n\t\t\tin.isTopLevel ? (\n\t\t\t\tprint: \"']' without matching '['\"\n\t\t\t\terror: tru\n\t\t\t)|(\n\t\t\t\t(Bool: data.get: offset) ? (\n\t\t\t\t\ti: in.start-1\n\t\t\t\t)|(\n\t\t\t\t\tquit: tru\n\t\t\t\t)\n\t\t\t)\n\t\t)\n\t\t\n\t\ti: i+1\n\t\t\n\t\ti >= in.src.len ? (\n\t\t\tin.isTopLevel ? (\n\t\t\t\tquit: tru\n\t\t\t)|(\n\t\t\t\tprint: \"'[' without matching ']'\"\n\t\t\t\terror: tru\n\t\t\t)\n\t\t)\n\t)\n)\n\nskipBrace :: {src: String, i: Int} -> {Int}: (\n\t\n\ti: in.i\n\t\n\t(in.src.sub: i, i+1) != \"[\" ? (\n\t\tprint: \"skipBrace called on character other then '['\"\n\t\terror: tru\n\t)|(\n\t\n\ti: i+1\n\t\n\t!error && (in.src.sub: i, i+1) != \"]\" @ (\n\t\ti: i+1\n\t\ti >= in.src.len ? (\n\t\t\tprint: \"'[' without matching ']'\"\n\t\t\terror: tru\n\t\t)\n\t)\n\t\n\t)\n\t\t\t\t\t\t\t\t\t\t\t\n\ti\n)\n\n#>++++++++[-<+++++++++>]<.>>+>-[+]++>++>+++[>[->+++<<+++>]<<]>-----.>->+++..+++.>-.<<+[>[+>+]>>]<--------------.>>.+++.------.--------.>+.>+.\n\n"
  },
  {
    "path": "examples/fizzBuzz.pn",
    "content": "# FizzBuzz\n\n# call the function defined below\nfizzBuzz: 1, 20\n\n# define the FizzBuzz function\nfizzBuzz :: {start: Int, end: Int}: (\n\t\n\t# loop i from start to end\n\ti: in.start | i <= in.end | i: i+1 @ (\n\t\t\n\t\t# use conditionals to print the right thing\n\t\t\n\t\ti % 3 = 0 && i % 5 = 0 ?\n\t\t\tprint: \"FizzBuzz\"\n\t\t|\n\t\ti % 3 = 0 ?\n\t\t\tprint: \"Fizz\"\n\t\t|\n\t\ti % 5 = 0 ?\n\t\t\tprint: \"Buzz\"\n\t\t|\n\t\t\tprint: i\n\t)\n)\n"
  },
  {
    "path": "examples/hello_world.pn",
    "content": "print: \"Hello World!\"\n\n"
  },
  {
    "path": "examples/historical/snake_original.pn",
    "content": "# this was written on Jan 12th, 2016.\n# this is the first complex pinecone program ever wretten.\n# type the numbers 1, 2, 3 and 4 followed by enter to move.\n# because of how early it was wretten, it doesn't use modern constructs, like functions.\n\nw :: 16\nh :: 8\n\nmeChar :: 79\ntrailChar :: 43\n\n# init\n\nlocX: w/2\nlocY: h/2\n\nquit: fls\n\nary: IntArray: w*h\n\ny: 0 | y<h | y: y+1 @\n(\n\tx: 0 | x<w | x: x+1 @\n\t(\n\t\tary.set: y*w+x, 32\n\t)\n)\n\n# game loop\n\n!quit @\n(\n\t# update\n\t\n\tlocX<0? locX: 0\n\tlocX>=w? locX: w-1\n\tlocY<0? locY: 0\n\tlocY>=h? locY: h-1\n\t\n\t(ary.get: locY*w+locX)=trailChar ?\n\t(\n\t\tquit: tru\n\t)|(\n\t\tary.set: locY*w+locX, trailChar\n\t\t\n\t\t\n\t\t# display board\n\t\t\n\t\ti: 0 | i<6 | i: i+1 @\n\t\t\tprint\n\t\t\n\t\tprintc: 32\n\t\t\n\t\tx: 0 | x<w | x: x+1 @\n\t\t\tprintc: 45\n\t\t\n\t\tprint\n\t\t\n\t\ty: 0 |y<h |y: y+1 @\n\t\t(\n\t\t\tprintc: 124\n\t\t\t\n\t\t\tx: 0 | x<w | x: x+1 @\n\t\t\t(\n\t\t\t\tx=locX && y=locY ?\n\t\t\t\t\tprintc: meChar\n\t\t\t\t|\n\t\t\t\t\tprintc: ary.get: y*w+x\n\t\t\t)\n\t\t\t\n\t\t\tprintc: 124\n\t\t\tprint\n\t\t)\n\t\t\n\t\tprintc: 32\n\t\t\n\t\tx: 0 | x<w | x: x+1 @\n\t\t\tprintc: 45\n\t\t3\n\t\t\n\t\tprint\n\t\t\n\t\t# get input\n\t\t\n\t\tvalid: fls\n\t\t\n\t\t!valid @\n\t\t(\n\t\t\tdir: inputInt\n\t\t\tvalid: tru\n\t\t\t\n\t\t\tdir=3 ?\n\t\t\t\tlocY: locY+1\n\t\t\t| dir=4 ?\n\t\t\t\tlocX: locX+1\n\t\t\t| dir=2 ?\n\t\t\t\tlocY: locY-1\n\t\t\t| dir=1 ?\n\t\t\t\tlocX: locX-1\n\t\t\t|\n\t\t\t\tvalid: fls\n\t\t)\n\t)\n)\n\nprint\nprintc: 88\nprintc: 32\nprintc: 88\nprint\nprintc: 45\nprintc: 45\nprintc: 45\nprint\n"
  },
  {
    "path": "examples/incomplete/hashmap.pn",
    "content": "\nHashmap :: {used: IntArray, keys: IntArray, vals: IntArray}\n\nHashmap :: {} -> {Hashmap}:\n(\n\tsize: 10\n\tused: (IntArray: size)\n\ti: 0 | i<used.len | i: i+1 @ (\n\t\tused.set: i, 0\n\t)\n\t\n\tused, (IntArray: size), (IntArray: size)\n)\n\nHashmap :: {size: Int} -> {Hashmap}:\n(\n\tused: (IntArray: size)\n\ti: 0 | i<used.len | i: i+1 @ (\n\t\tused.set: i, 0\n\t)\n\t\n\tused, (IntArray: size), (IntArray: size)\n)\n\ninsert :: {Hashmap}.{key: Int, val: Int}:\n(\n\ti: in.key % me.used.len\n\tstart: i\n\t\n\tBool: me.used.get: i @ (\n\t\ti: (i+1) % me.used.len\n\t\t#i = start ?\n\t\t#\tme.expand\n\t)\n\t\n\tme.used.set: i, 1\n\tme.keys.set: i, in.key\n\tme.vals.set: i, in.val\n)\n\nlen :: {Hashmap}.{} -> {Int}: me.keys.len\n\nString :: {Hashmap} -> {String}:\n(\n\tout: \"hashmap:\\n\"\n\t\n\ti: 0 | i<in.len | i: i+1 @\n\t(\n\t\tBool: in.used.get: i ?\n\t\t\tout: out + \"\\t\" + (in.keys.get: i).String + \": \" + (in.vals.get: i).String + \"\\n\"\n\t)\n\t\n\tout\n)\n\na: Hashmap\n\na.insert: 4, 82\na.insert: 14, 89\n\nprint: String: a\n"
  },
  {
    "path": "examples/morse.pn",
    "content": "# this program converts text into morse code\n\n# this constant string will act as the data source for the conversion\nkey :: \"a.- b-... c-.-. d-.. e. f..-. g--. h.... i.. j.--- k-.- l.-.. m-- n-. o--- p.--. q--.- r.-. s... t- u..- v...- w.-- x-..- y-.-- z--.. 1.---- 2..--- 3...-- 4....- 5..... 6-.... 7--... 8---.. 9----. 0----- ..-.-.- ?..--.. \"\n\n# loop until the user types \"quit\"\n\nquit: fls\n\n!quit @\n(\n\t# get input\n\tinStr: \"enter some text or type quit: \".input\n\t\n\tinStr = \"quit\" ?\n\t\tquit: tru\n\t|\n\t\tprint: stringToMorse: inStr\n)\n\nprint\n\nstringToMorse :: {String} -> {String}:\n(\n\tout: \"\"\n\ti: 0 | i<in.len | i: i+1 @\n\t(\n\t\tletter: in.sub: i, i+1\n\t\t\n\t\tletter = \" \" ?\n\t\t\tout: out+\"    \"\n\t\t|\n\t\t\tout: out+(letterToMorse: letter)+\" \"\n\t)\n\t\n\tout\n)\n\nletterToMorse :: {String} -> {String}:\n(\t\n\tout: \"\"\n\t\n\tfound: fls\n\t\n\ti: 0 | i<key.len && !found | i: i+1 @\n\t(\n\t\t(key.sub: i, i+1) = in ?\n\t\t(\n\t\t\tj: i+1\n\t\t\t \n\t\t\t!((key.sub: j, j+1) = \" \") @\n\t\t\t\tj: j+1\n\t\t\t\n\t\t\tout: key.sub: i+1, j\n\t\t\t\n\t\t\tfound: tru\n\t\t)\n\t)\n\t\n\t!found ?\n\t\tout: \"[\" + in + \"]\"\n\t\n\tout\n)\n"
  },
  {
    "path": "examples/queue.pn",
    "content": "# this is an implementation of a queue using a dynamically sized circular buffer\n# this was wretten for Pinecone v0.3, which does not yet have references, so a single global queue is used instead of a queue object\n\nq: Queue\nmain\n\nmain :: {}:\n(\n\tenqueue: 1\n\tenqueue: 2\n\tenqueue: 3\n\tenqueue: 4\n\tenqueue: 5\n\tenqueue: 6\n\t\n\tprint: dequeue\n\tprint: dequeue\n\tprint: dequeue\n\tprint: dequeue\n\t\n\tenqueue: 7\n\tenqueue: 8\n\tenqueue: 9\n\t\n\tprint: dequeue\n\tprint: dequeue\n\t\n\tprint: q\n)\n\nQueue :: {array: IntArray, offset: Int, len: Int}\n\nQueue :: {} -> {Queue}: (\n\t(IntArray: 1), 0, 0\n)\n\nresize :: {Int}: (\n\t\n\tnewArray: IntArray: in\n\t\n\ti: 0 | i<q.len | i: i+1 @ (\n\t\ttmp: q.array\n\t\tnewArray.set: i, (tmp.get: (i+q.offset)%q.array.len)\n\t)\n\t\n\tq: newArray, 0, q.len\n)\n\nenqueue :: {Int}: (\n\t\n\tq.len >= q.array.len ?\n\t\tresize: q.array.len*2\n\t\n\tq: q.array, q.offset, q.len+1\n\t\n\ttmp: q.array\n\ttmp.set: (q.offset+q.len-1)%q.array.len, in\n)\n\ndequeue :: {} -> {Int}: (\n\t\n\ttmp: q.array\n\tout: tmp.get: q.offset%q.array.len\n\tq: q.array, q.offset+1, q.len-1\n\t\n\tq.len < q.array.len/3+1 ?\n\t\tresize: q.array.len/3+1\n\t\n\tout\n)\n\npeek :: {}: (\n\ttmp: q.array\n\ttmp.get: q.offset%q.array.len\n)\n\nprint :: {Queue}: (\n\t\n\tprint: \"queue {\"\n\ti: 0 | i<in.len | i: i+1 @ (\n\t\t#Bool: i ?\n\t\t#\tprint: \", \"\n\t\tary: in.array\n\t\tprint: \"    \"+(ary.get: (i+in.offset)%in.array.len).String\n\t)\n\tprint: \"}\"\n\tprint\n\t\n\t//\n\tprint: \"raw array {\"\n\ti: 0 | i<in.array.len | i: i+1 @ (\n\t\t#Bool: i ?\n\t\t#\tprint: \", \"\n\t\tary: in.array\n\t\tout: (ary.get: i).String\n\t\ti = in.offset ?\n\t\t\tout: \" -> \"+out\n\t\t| i = (in.offset+in.len-1)%in.array.len ?\n\t\t\tout: \" -| \"+out\n\t\t|\n\t\t\tout: \"    \"+out\n\t\tprint: out\n\t)\n\tprint: \"}\"\n\tprint\n\t\\\\\n)\n\n\n\n"
  },
  {
    "path": "examples/readme.md",
    "content": "These are some examples of working Pinecone source code\n"
  },
  {
    "path": "examples/simple_demo.pn",
    "content": "\n//\nThis file demonstrates the basic syntax constructs of Pinecone\n\nto run, simply run command\npath/to/pinecone/executable simple_demo.pn\n\\\\\n\n# that was a multi line comment. this is a single line comment\n\n# create a variable\na: 12 # deduces the type as Int\n\n# print the value in the variable\nprint: a\n\nprint # print an empty line\n\nprint: \"if/then\"\n\nb: 7\n\na = 9 ?\n(\n\tprint: 1\n)|(\n\tprint: 2\n)\n\nb>3 ?\n(\n\tprint: 3\n)\n\nprint\n\n\nprint: \"while loop\"\n\ni: 12\n\ni>3 @\n(\n\tprint: i\n\ti: i-1\n)\n\nprint\n\n\nprint: \"for loop\"\n\ni: 0 | i<10 | i: i+1 @\n(\n\tprint: i\n)\n\nprint\n\n\nprint: \"functions\"\n\nprint: func: 7\n\nfunc :: {Int} -> {Dub}:\n(\n\t(Dub: in)/2.0\n)\n\nprint\n\n\nprint: \"Fibonacci\"\n\nb: 0\na: 1\n\na<100 @\n(\n\tprint: a\n\ttmp: a\n\ta: a+b\n\tb: tmp\n)\n\nprint\n\n\nprint: \"Recursive Fibonacci\"\n\nfib :: {Int} -> {Int}: (\n\tout: Int\n\t\n\tin <= 1 ?\n\t\tout: 1\n\t|\n\t\tout: (fib: in - 1) + (fib: in - 2)\n\t\n\tout\n)\n\nprint: fib: 8\n\nprint\n\nprint: \"compile time constants\"\n# these can be declared in any order\n\nprint: y\n\nx :: 10\ny :: x+z\nz :: 4\n\n\n"
  },
  {
    "path": "examples/snake_new.pn",
    "content": "# this is an updated version of the original Pinecone snake game\n# use WASD to move\n\nw :: 16\nh :: 8\n\nmeChar :: 79\ntrailChar :: 43\n\n# init\n\nlocX: w/2\nlocY: h/2\n\nquit: fls\n\nary: IntArray: w*h\n\nclearBoard\n\n# game loop\n\n!quit @\n(\n\t# update\n\t\n\tlocX<0? locX: 0\n\tlocX>=w? locX: w-1\n\tlocY<0? locY: 0\n\tlocY>=h? locY: h-1\n\t\n\t(ary.get: locY*w+locX)=trailChar ?\n\t(\n\t\tquit: tru\n\t)|(\n\t\tdrawBoard\n\t\t\n\t\tary.set: locY*w+locX, trailChar\n\t\t\n\t\t# get input\n\t\t\n\t\tvalid: fls\n\t\t\n\t\t!valid @\n\t\t(\n\t\t\tdir: \"use WASD to move, then press return: \".input\n\t\t\tvalid: tru\n\t\t\t\n\t\t\tdir=\"s\" ?\n\t\t\t\tlocY: locY+1\n\t\t\t| dir=\"d\" ?\n\t\t\t\tlocX: locX+1\n\t\t\t| dir=\"w\" ?\n\t\t\t\tlocY: locY-1\n\t\t\t| dir=\"a\" ?\n\t\t\t\tlocX: locX-1\n\t\t\t|\n\t\t\t\tvalid: fls\n\t\t)\n\t)\n)\n\nclearBoard :: {}:\n(\n\ty: 0 | y<h | y: y+1 @\n\t(\n\t\tx: 0 | x<w | x: x+1 @\n\t\t(\n\t\t\tary.set: y*w+x, 32\n\t\t)\n\t)\n)\n\ndrawBoard :: {}:\n(\t\n\ti: 0 | i<12 | i: i+1 @\n\t\tprint\n\t\n\tline: \" \"\n\t\n\tx: 0 | x<w | x: x+1 @\n\t\tline: line+\"-\"\n\t\n\tprint: line\n\tline: \"\"\n\t\n\ty: 0 |y<h |y: y+1 @\n\t(\n\t\tline: line+\"|\"\n\t\t\n\t\tx: 0 | x<w | x: x+1 @\n\t\t(\n\t\t\tx=locX && y=locY ?\n\t\t\t\tline: line+(meChar.ascii)\n\t\t\t|\n\t\t\t\tline: line+(ary.get: y*w+x).ascii\n\t\t)\n\t\t\n\t\tline: line+\"|\"\n\t\tprint: line\n\t\tline: \"\"\n\t)\n\t\n\tline: \" \"\n\t\n\tx: 0 | x<w | x: x+1 @\n\t\tline: line+\"-\"\n\t\n\tprint: line\n)\n\nprint\nprintc: 88\nprintc: 32\nprintc: 88\nprint\nprintc: 45\nprintc: 45\nprintc: 45\nprint\n"
  },
  {
    "path": "h/Action.h",
    "content": "#pragma once\n\n#include \"StackFrame.h\"\n#include \"Type.h\"\n#include \"CppProgram.h\"\n#include <functional>\n#include <memory>\n#include <vector>\n#include <string>\n#include \"utils/stringDrawing.h\"\n\n\n#include <stdlib.h> // malloc() and free() on some systems\n\nusing std::shared_ptr;\nusing std::unique_ptr;\nusing std::to_string;\nusing std::function;\nusing std::vector;\n\nclass ActionData;\n\nextern shared_ptr<ActionData> voidAction;\n\nclass ActionData\n{\npublic:\n\t\n\tActionData(Type returnTypeIn, Type inLeftTypeIn, Type inRightTypeIn);\n\t\n\tvirtual ~ActionData() {}\n\t\n\tvoid setDescription(string in) {description=in;}\n\t\n\t//void setText(string in) {text=in;}\n\t//string getText() {return text;}\n\tstring toString();\n\tstring getTypesString();\n\tvirtual bool isFunction() {return false;}\n\t\n\tType& getReturnType() {return returnType;}\n\tType& getInLeftType() {return inLeftType;}\n\tType& getInRightType() {return inRightType;}\n\t//void* execute(void* inLeft, void* inRight);\n\t\n\tvirtual string getDescription() {return description;}\n\tvirtual void* execute(void* inLeft, void* inRight)=0;\n\t//virtual string getCSource(string inLeft=\"\", string inRight=\"\")=0;\n\tvirtual void addToProg(shared_ptr<ActionData> inLeft, shared_ptr<ActionData> inRight, CppProgram* prog)\n\t{\n\t\tprog->comment(\"action '\"+getDescription()+\"' to cpp code not yet implemented\");\n\t}\n\tvoid addToProg(CppProgram* prog) {addToProg(voidAction, voidAction, prog);}\n\t// void addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t\n\tstring nameHint=\"\";\n\t\nprotected:\n\t\n\t//string text;\n\t\n\tType returnType;\n\tType inLeftType;\n\tType inRightType;\n\tstring description;\n\t//virtual DataElem * privateExecute(DataElem * inLeft, DataElem * inRight)=0;\n};\n\ntypedef shared_ptr<ActionData> Action;\n\nclass AstNodeBase;\n\n//Action lambdaAction(Type returnTypeIn, function<void*(void*,void*)> lambdaIn, Type inLeftTypeIn, Type inRightTypeIn, string textIn);\nAction lambdaAction(Type inLeftTypeIn, Type inRightTypeIn, Type returnTypeIn, function<void*(void*,void*)> lambdaIn, function<void(Action inLeft, Action inRight, CppProgram* prog)> addCppToProg, string textIn);\nAction createNewVoidAction();\n\nAction branchAction(Action leftInputIn, Action actionIn, Action rightInputIn);\n\nAction functionAction(Action actionIn, shared_ptr<StackFrame> stackFameIn);\nAction functionAction(unique_ptr<AstNodeBase> nodeIn, Type returnTypeIn, shared_ptr<StackFrame> stackFameIn);\n\nAction andAction(Action firstActionIn, Action secondActionIn);\nAction orAction(Action firstActionIn, Action secondActionIn);\n\nAction ifAction(Action conditionIn, Action ifActionIn);\nAction ifElseAction(Action conditionIn, Action ifActionIn, Action elseAction);\n\nAction listAction(const std::vector<Action>& actionsIn, const std::vector<Action>& destroyersIn);\n\nAction loopAction(Action conditionIn, Action loopActionIn);\nAction loopAction(Action conditionIn, Action endActionIn, Action loopActionIn);\n\nAction makeTupleAction(const std::vector<Action>& sourceActionsIn);\n//Action getElemFromTupleAction(Action source, string name);\nAction getElemFromTupleAction(Type source, string name);\nAction cppTupleCastAction(Action actionIn, Type returnType);\n\nAction varGetAction(size_t in, Type typeIn, string idIn);\nAction varSetAction(size_t in, Type typeIn, string idIn);\nAction globalGetAction(size_t in, Type typeIn, string idIn);\nAction globalSetAction(size_t in, Type typeIn, string idIn);\n\nclass NamespaceData;\nAction constGetAction(const void* in, Type typeIn, string idIn, shared_ptr<NamespaceData> ns);\n\nAction typeGetAction(Type typeIn);\n\n"
  },
  {
    "path": "h/AllOperators.h",
    "content": "#pragma once\n\n#include <vector>\nusing std::vector;\n\n#include <unordered_map>\nusing std::unordered_map;\n\n#include \"Operator.h\"\n\nclass AllOperators\n{\npublic:\n\t\n\t// sets ops to a new instance\n\tstatic void init();\n\t\n\t// sets out to the operators (0, 1 or more) for the given text\n\tvoid get(string text, vector<Operator>& out);\n\t\n\t/*\n\t#define DECLARE_OP(name, text, left, right, overload)\\\n\t\tconst Operator name{new OperatorData(text, left, right, overload)};\n\t\n\t#define ALL_OPS\t\t\t\t\t\t\t\t\t\t\t\\\n\tDECLARE_OP(\tloop,\t\t\"@\",\t5,\t\t5,\t\tfalse\t);\t\\\n\tDECLARE_OP(\tifOp,\t\t\"?\",\t5,\t\t5,\t\tfalse\t);\t\\\n\tDECLARE_OP(\tpipe,\t\t\"|\",\t10,\t\t10,\t\tfalse\t);\t\\\n\tDECLARE_OP(\tplus,\t\t\"+\",\t20,\t\t21,\t\ttrue\t);\t\\\n\tDECLARE_OP(\tminus,\t\t\"-\",\t20,\t\t21,\t\ttrue\t);\t\\\n\tDECLARE_OP(\tmultiply,\t\"*\",\t30,\t\t31,\t\ttrue\t);\t\\\n\tDECLARE_OP(\tdivide,\t\t\"/\",\t30,\t\t31,\t\ttrue\t);\t\\\n\tDECLARE_OP(\tequal,\t\t\"=\",\t40,\t\t41,\t\ttrue\t);\t\\\n\tDECLARE_OP(\tgreater,\t\">\",\t40,\t\t41,\t\ttrue\t);\t\\\n\tDECLARE_OP(\tless,\t\t\"<\",\t40,\t\t41,\t\ttrue\t);\t\\\n\tDECLARE_OP(\tcomma,\t\t\",\",\t60,\t\t61,\t\tfalse\t);\t\\\n\tDECLARE_OP(\tdot,\t\t\".\",\t70,\t\t71,\t\tfalse\t);\t\\\n\tDECLARE_OP(\tdoubleColon,\"::\",\t13,\t\t12,\t\tfalse\t);\t\\\n\tDECLARE_OP(\tcolon,\t\t\":\",\t15,\t\t14,\t\tfalse\t);\t\\\n\tDECLARE_OP(\topenPeren,\t\"(\",\t0,\t\t100,\tfalse\t);\t\\\n\tDECLARE_OP(\tclosePeren,\t\")\",\t100,\t0,\t\tfalse\t);\t\\\n\tDECLARE_OP(\topenSqBrac,\t\"[\",\t0,\t\t100,\tfalse\t);\t\\\n\tDECLARE_OP(\tcloseSqBrac,\"]\",\t100,\t0,\t\tfalse\t);\t\\\n\tDECLARE_OP(\topenCrBrac,\t\"{\",\t0,\t\t100,\tfalse\t);\t\\\n\tDECLARE_OP(\tcloseCrBrac,\"}\",\t100,\t0,\t\tfalse\t);\t\\\n\t*/\n\t\n\t#define DECLARE_OP(name, text, prece, input, overload)\\\n\t\tconst Operator name{new OperatorData(text, prece, input, overload)};\n\t\n\t#define ALL_OPS\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tDECLARE_OP(\tloop,\t\t\"@\",\t5,\t\tOperatorData::BOTH,\t\tfalse\t);\t\\\n\tDECLARE_OP(\tifOp,\t\t\"?\",\t6,\t\tOperatorData::BOTH,\t\tfalse\t);\t\\\n\tDECLARE_OP(\tpipe,\t\t\"|\",\t6,\t\tOperatorData::BOTH,\t\tfalse\t);\t\\\n\tDECLARE_OP(\tcolon,\t\t\":\",\t24,\t\tOperatorData::BOTH,\t\tfalse\t);\t\\\n\tDECLARE_OP(\tdoubleColon,\"::\",\t24,\t\tOperatorData::BOTH,\t\tfalse\t);\t\\\n\tDECLARE_OP(\tcomma,\t\t\",\",\t35,\t\tOperatorData::BOTH,\t\tfalse\t);\t\\\n\tDECLARE_OP(\torOp,\t\t\"||\",\t36,\t\tOperatorData::BOTH,\t\tfalse\t);\t\\\n\tDECLARE_OP(\tandOp,\t\t\"&&\",\t38,\t\tOperatorData::BOTH,\t\tfalse\t);\t\\\n\tDECLARE_OP(\tequal,\t\t\"=\",\t40,\t\tOperatorData::BOTH,\t\ttrue\t);\t\\\n\tDECLARE_OP(\tnotEqual,\t\"!=\",\t40,\t\tOperatorData::BOTH,\t\tfalse\t);\t\\\n\tDECLARE_OP(\tgreater,\t\">\",\t50,\t\tOperatorData::BOTH,\t\ttrue\t);\t\\\n\tDECLARE_OP(\tless,\t\t\"<\",\t50,\t\tOperatorData::BOTH,\t\ttrue\t);\t\\\n\tDECLARE_OP(\tgreaterEq,\t\">=\",\t50,\t\tOperatorData::BOTH,\t\ttrue\t);\t\\\n\tDECLARE_OP(\tlessEq,\t\t\"<=\",\t50,\t\tOperatorData::BOTH,\t\ttrue\t);\t\\\n\tDECLARE_OP(\tplus,\t\t\"+\",\t61,\t\tOperatorData::BOTH,\t\ttrue\t);\t\\\n\tDECLARE_OP(\tminus,\t\t\"-\",\t61,\t\tOperatorData::BOTH,\t\ttrue\t);\t\\\n\tDECLARE_OP(\tmultiply,\t\"*\",\t71,\t\tOperatorData::BOTH,\t\ttrue\t);\t\\\n\tDECLARE_OP(\tdivide,\t\t\"/\",\t71,\t\tOperatorData::BOTH,\t\ttrue\t);\t\\\n\tDECLARE_OP(\tmod,\t\t\"%\",\t70,\t\tOperatorData::BOTH,\t\ttrue\t);\t\\\n\tDECLARE_OP(\tnotOp,\t\t\"!\",\t74,\t\tOperatorData::RIGHT,\ttrue\t);\t\\\n\tDECLARE_OP(\tplusPlus,\t\"++\",\t75,\t\tOperatorData::LEFT,\t\tfalse\t);\t\\\n\tDECLARE_OP(\tminusMinus,\t\"--\",\t75,\t\tOperatorData::LEFT,\t\tfalse\t);\t\\\n\tDECLARE_OP(\tdot,\t\t\".\",\t81,\t\tOperatorData::BOTH,\t\tfalse\t);\t\\\n\tDECLARE_OP(\trightArrow,\t\"->\",\t83,\t\tOperatorData::BOTH,\t\tfalse\t);\t\\\n\tDECLARE_OP(\timport,\t\t\"==>\",\t90,\t\tOperatorData::RIGHT,\tfalse\t);\t\\\n\tDECLARE_OP(\topenPeren,\t\"(\",\t100,\tOperatorData::RIGHT,\tfalse\t);\t\\\n\tDECLARE_OP(\tclosePeren,\t\")\",\t99,\t\tOperatorData::LEFT,\t\tfalse\t);\t\\\n\tDECLARE_OP(\topenSqBrac,\t\"[\",\t100,\tOperatorData::BOTH,\t\tfalse\t);\t\\\n\tDECLARE_OP(\tcloseSqBrac,\"]\",\t99,\t\tOperatorData::LEFT,\t\tfalse\t);\t\\\n\tDECLARE_OP(\topenCrBrac,\t\"{\",\t100,\tOperatorData::RIGHT,\tfalse\t);\t\\\n\tDECLARE_OP(\tcloseCrBrac,\"}\",\t99,\t\tOperatorData::LEFT,\t\tfalse\t);\t\\\n\t\n\tALL_OPS;\n\t\n\t// for read only, dont screw with this\n\tunordered_map<string, Operator>& getOpsMap() {return opsMap;}\n\t\n\t// returns if the given operator is an opening bracket or peren\n\tbool isOpenBrac(Operator op);\n\tbool isCloseBrac(Operator op);\n\t\nprivate:\n\t\n\t// is only called in init\n\tAllOperators();\n\t\n\t// used internally by the constructor\n\tvoid putOpInMap(Operator op);\n\t\n\t// a hash map of all the operators\n\tunordered_map<string, Operator> opsMap;\n};\n\n// the single instance of this class, starts out as nullptr but chages to a real instance in AllOperators::init\n//extern shared_ptr<AllOperators> ops;\nextern AllOperators* ops;\n"
  },
  {
    "path": "h/AstNode.h",
    "content": "#pragma once\n\n#include \"Token.h\"\n#include \"Action.h\"\n#include \"ErrorHandler.h\"\n\nclass NamespaceData;\ntypedef shared_ptr<NamespaceData> Namespace;\n\n#include <vector>\nusing std::vector;\n\nclass AstNodeBase;\ntypedef unique_ptr<AstNodeBase> AstNode;\n\nAstNode astNodeFromTokens(const vector<Token>& tokens, int left, int right);\n\nclass AstNodeBase\n{\npublic:\n\n\tvirtual ~AstNodeBase() = default;\n\t\n\tvoid setInput(Namespace nsIn, bool dynamicIn, Type left, Type right)\n\t{\n\t\tif (inputHasBeenSet)\n\t\t{\n\t\t\tthrow PineconeError(\"tried to set input on an AST node '\"+getString()+\"' more then once\", INTERNAL_ERROR, getToken());\n\t\t}\n\t\t\n\t\tinputHasBeenSet=true;\n\t\t\n\t\tns=nsIn;\n\t\tdynamic=dynamicIn;\n\t\tinLeftType=left;\n\t\tinRightType=right;\n\t}\n\t\n\tvirtual bool isVoid() {return false;}\n\tvirtual bool isType() {return false;}\n\tvirtual bool isFunctionWithOutput() {return false;}\n\t\n\t/*\n\tType getInLeftType()\n\t{\n\t\tif (!inputHasBeenSet)\n\t\t\tthrow PineconeError(\"tried to get inLeftType before input was set\", INTERNAL_ERROR, getToken());\n\t\treturn inLeftType;\n\t}\n\t\n\tType getInRightType()\n\t{\n\t\tif (!inputHasBeenSet)\n\t\t\tthrow PineconeError(\"tried to get inRightType before input was set\", INTERNAL_ERROR, getToken());\n\t\treturn inRightType;\n\t}\n\t*/\n\t\n\tvirtual string getString()=0;\n\t\n\tvirtual AstNode makeCopy(bool copyCache)=0; // if copyCache is false, input and actions will not be copied\n\t\n\tvirtual bool canBeWhatev() {return false;}\n\t\n\t// returns nullptr if it can't do it\n\tvirtual AstNode makeCopyWithSpecificTypes(Type leftInType, Type rightInType) {return nullptr;}\n\t\n\tType getReturnType()\n\t{\n\t\tif (!returnType)\n\t\t{\n\t\t\tif (!inputHasBeenSet)\n\t\t\t{\n\t\t\t\tthrow PineconeError(\"tried to get return type from AST node when input had not been set\", INTERNAL_ERROR, getToken());\n\t\t\t}\n\t\t\t\n\t\t\tresolveReturnType();\n\t\t}\n\t\t\n\t\tif (!returnType)\n\t\t{\n\t\t\tthrow PineconeError(\"AST node \"+getString()+\"failed to supply a return type\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\treturn returnType;\n\t}\n\t\n\tAction getAction()\n\t{\n\t\tif (!action)\n\t\t{\n\t\t\tif (!ns)\n\t\t\t{\n\t\t\t\tthrow PineconeError(\"tried to get action from AST node when input had not been set\", INTERNAL_ERROR, getToken());\n\t\t\t}\n\t\t\t\n\t\t\tresolveAction();\n\t\t\t\n\t\t\tif (!nameHint.empty())\n\t\t\t\taction->nameHint=nameHint;\n\t\t}\n\t\t\n\t\treturn action;\n\t}\n\t\n\tvoid dealWithConstants()\n\t{\n\t\tif (!ns)\n\t\t{\n\t\t\tthrow PineconeError(\"tried to deal with constants before input was set\", INTERNAL_ERROR, getToken());\n\t\t}\n\t\t\n\t\tresolveConstant();\n\t}\n\t\n\t// primarily used for error throwing, can return null\n\tvirtual Token getToken()=0;\n\t\n\tstring nameHint=\"\";\n\tvirtual void nameHintSet() {}\n\t\nprotected:\n\t\n\tAstNodeBase() {}\n\t\n\tvoid copyToNode(AstNodeBase* other, bool copyCache);\n\t\n\tvirtual void resolveReturnType()\n\t{\n\t\treturnType=getAction()->getReturnType();\n\t}\n\t\n\tvirtual void resolveAction()=0;\n\tvirtual void resolveConstant() {};\n\t\n\tType inLeftType=nullptr, inRightType=nullptr;\n\tAction action=nullptr;\n\tType returnType=nullptr;\n\tbool dynamic=false;\n\tNamespace ns=nullptr;\n\tbool inputHasBeenSet=false;\n};\n\nclass AstVoid: public AstNodeBase\n{\npublic:\n\t\n\tstatic unique_ptr<AstVoid> make() {return unique_ptr<AstVoid>(new AstVoid);}\n\t\n\tbool isVoid() {return true;}\n\t\n\tstring getString() {return \"void node\";}\n\t\n\tAstNode makeCopy(bool copyCache)\n\t{\n\t\tauto out=new AstVoid;\n\t\tcopyToNode(out, copyCache);\n\t\treturn AstNode(out);\n\t}\n\t\n\tvoid resolveReturnType() {returnType=Void;}\n\t\n\tvoid resolveAction()\n\t{\n\t\tif (!inLeftType->isVoid() || !inRightType->isVoid())\n\t\t{\n\t\t\tthrow PineconeError(\"AstVoid given non void input\", INTERNAL_ERROR, getToken());\n\t\t}\n\t\t\n\t\taction=voidAction;\n\t}\n\t\n\tToken getToken() {return nullptr;}\n};\n//extern AstNode astVoid;\n\nclass AstList: public AstNodeBase\n{\npublic:\n\t\n\t//\tmake a new instance of this type of node\n\tstatic unique_ptr<AstList> make(vector<AstNode>& in)\n\t{\n\t\tunique_ptr<AstList> node(new AstList);\n\t\tnode->nodes=move(in);\n\t\treturn node;\n\t}\n\t\n\tstring getString();\n\t\n\tAstNode makeCopy(bool copyCache)\n\t{\n\t\tauto out=new AstList;\n\t\tcopyToNode(out, copyCache);\n\t\tfor (int i=0; i<(int)nodes.size(); i++)\n\t\t{\n\t\t\tout->nodes.push_back(nodes[i]->makeCopy(copyCache));\n\t\t}\n\t\treturn AstNode(out);\n\t}\n\t\n\t//void resolveReturnType();\n\t\n\tvoid resolveAction();\n\t\n\tToken getToken() {return nodes.empty()?nullptr:nodes[0]->getToken();}\n\t\nprivate:\n\t\n\t//\tthe list of sub nodes\n\tvector<AstNode> nodes;\n};\n\nclass AstConstExpression;\n\nclass AstToken: public AstNodeBase\n{\npublic:\n\t\n\tstatic unique_ptr<AstToken> make(Token tokenIn)\n\t{\n\t\tunique_ptr<AstToken> node(new AstToken);\n\t\tnode->token=tokenIn;\n\t\treturn node;\n\t}\n\t\n\tstring getString();\n\t\n\tAstNode makeCopy(bool copyCache)\n\t{\n\t\tauto out=new AstToken;\n\t\tcopyToNode(out, copyCache);\n\t\tout->token=token;\n\t\treturn AstNode(out);\n\t}\n\t\n\tvoid resolveAction();\n\t\n\tToken getToken() {return token;}\n\t\nprivate:\n\t\n\tfriend AstConstExpression;\n\t\n\tToken token=nullptr;\n};\n\nclass AstFuncBody: public AstNodeBase\n{\npublic:\n\t\n\tstatic AstNode make(AstNode leftTypeIn, AstNode rightTypeIn, AstNode returnTypeIn, AstNode bodyIn)\n\t{\n\t\tauto node=new AstFuncBody();\n\t\t\n\t\tif (!leftTypeIn->isType() || !rightTypeIn->isType() || !returnTypeIn->isType())\n\t\t{\n\t\t\tthrow PineconeError(\"AstFuncBody made with function input nodes that are not types\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\tnode->leftTypeNode=move(leftTypeIn);\n\t\tnode->rightTypeNode=move(rightTypeIn);\n\t\tnode->returnTypeNode=move(returnTypeIn);\n\t\tnode->bodyNode=move(bodyIn);\n\t\t\n\t\treturn AstNode(node);\n\t}\n\t\n\tstring getString();\n\t\n\tAstNode makeCopy(bool copyCache)\n\t{\n\t\tauto out=new AstFuncBody;\n\t\tcopyToNode(out, copyCache);\n\t\tout->leftTypeNode=leftTypeNode->makeCopy(copyCache);\n\t\tout->rightTypeNode=rightTypeNode->makeCopy(copyCache);\n\t\tout->returnTypeNode=returnTypeNode->makeCopy(copyCache);\n\t\tout->bodyNode=bodyNode->makeCopy(copyCache);\n\t\tout->typesInputSet=typesInputSet;\n\t\treturn AstNode(out);\n\t}\n\t\n\tvoid resolveAction();\n\t\n\tAstNode makeCopyWithSpecificTypes(Type leftInType, Type rightInType);\n\t\n\tToken getToken() {return bodyNode->getToken();}\n\t\n\tvoid setTypesInput()\n\t{\n\t\tif (!typesInputSet)\n\t\t{\n\t\t\tleftTypeNode->setInput(ns, false, Void, Void);\n\t\t\trightTypeNode->setInput(ns, false, Void, Void);\n\t\t\treturnTypeNode->setInput(ns, false, Void, Void);\n\t\t\ttypesInputSet=true;\n\t\t}\n\t}\n\t\n\tbool canBeWhatev()\n\t{\n\t\tsetTypesInput();\n\t\t\n\t\treturn\n\t\t\tleftTypeNode->getReturnType()->isWhatev() ||\n\t\t\trightTypeNode->getReturnType()->isWhatev() ||\n\t\t\treturnTypeNode->getReturnType()->isWhatev();\n\t\n\t}\n\t\n\tAstNode leftTypeNode, rightTypeNode, returnTypeNode, bodyNode;\n\tbool typesInputSet=false;\n};\n\nclass AstExpression: public AstNodeBase\n{\npublic:\n\t\n\tstatic unique_ptr<AstExpression> make(AstNode leftInIn, AstNode centerIn, AstNode rightInIn)\n\t{\n\t\tunique_ptr<AstExpression> node(new AstExpression);\n\t\t\n\t\tnode->leftIn=move(leftInIn);\n\t\tnode->center=move(centerIn);\n\t\tnode->rightIn=move(rightInIn);\n\t\t\n\t\treturn node;\n\t}\n\t\n\t//bool isType() {return leftIn->isType() || rightIn->isType();}\n\t\n\tAstNode makeCopy(bool copyCache)\n\t{\n\t\tauto out=new AstExpression;\n\t\tcopyToNode(out, copyCache);\n\t\tout->leftIn=leftIn->makeCopy(copyCache);\n\t\tout->center=center->makeCopy(copyCache);\n\t\tout->rightIn=rightIn->makeCopy(copyCache);\n\t\treturn AstNode(out);\n\t}\n\t\n\tstring getString();\n\t\n\tvoid resolveAction();\n\t\n\tToken getToken() {return center->getToken();}\n\t\n\tAstNode leftIn=nullptr, center=nullptr, rightIn=nullptr;\n};\n\nclass AstConstExpression: public AstNodeBase\n{\npublic:\n\t\n\tstatic unique_ptr<AstConstExpression> make(unique_ptr<AstToken> centerIn, AstNode rightInIn)\n\t{\n\t\tunique_ptr<AstConstExpression> node(new AstConstExpression);\n\t\t\n\t\t//node->leftIn=move(leftInIn);\n\t\tnode->center=move(centerIn);\n\t\tnode->rightIn=move(rightInIn);\n\t\t\n\t\treturn node;\n\t}\n\t\n\tstring getString();\n\t\n\tAstNode makeCopy(bool copyCache)\n\t{\n\t\tauto out=new AstConstExpression;\n\t\tcopyToNode(out, copyCache);\n\t\tout->center=unique_ptr<AstToken>((AstToken*)center->makeCopy(copyCache).release());;\n\t\tout->rightIn=center->makeCopy(copyCache);\n\t\treturn AstNode(out);\n\t}\n\t\n\tvoid resolveConstant();\n\tvoid resolveAction() {action=voidAction;};\n\t\n\tToken getToken() {return center->getToken();}\n\t\nprivate:\n\t\n\t//AstNode leftIn=nullptr;\n\tunique_ptr<AstToken> center=nullptr;\n\tAstNode rightIn=nullptr;\n};\n\nclass AstOpWithInput: public AstNodeBase\n{\npublic:\n\tstatic unique_ptr<AstOpWithInput> make(vector<AstNode>& leftInIn, Token tokenIn, vector<AstNode>& rightInIn)\n\t{\n\t\tunique_ptr<AstOpWithInput> node(new AstOpWithInput);\n\t\t\n\t\tnode->leftIn=move(leftInIn);\n\t\tnode->token=tokenIn;\n\t\tnode->rightIn=move(rightInIn);\n\t\t\n\t\treturn node;\n\t}\n\t\n\tbool isFunctionWithOutput();\n\t\n\tstring getString();\n\t\n\tAstNode makeCopy(bool copyCache)\n\t{\n\t\tauto out=new AstOpWithInput;\n\t\tcopyToNode(out, copyCache);\n\t\tout->token=token;\n\t\tfor (int i=0; i<(int)leftIn.size(); i++)\n\t\t{\n\t\t\tout->leftIn.push_back(leftIn[i]->makeCopy(copyCache));\n\t\t}\n\t\tfor (int i=0; i<(int)rightIn.size(); i++)\n\t\t{\n\t\t\tout->rightIn.push_back(rightIn[i]->makeCopy(copyCache));\n\t\t}\n\t\treturn AstNode(out);\n\t}\n\t\n\tvoid resolveAction();\n\t\n\tToken getToken() {return token;}\n\t\n\tToken token=nullptr;\n\tvector<AstNode> leftIn, rightIn;\n};\n\nclass AstTuple: public AstNodeBase\n{\npublic:\n\t\n\t//\tmake a new instance of this type of node\n\tstatic unique_ptr<AstTuple> make(vector<AstNode>& in)\n\t{\n\t\tunique_ptr<AstTuple> node(new AstTuple);\n\t\tnode->nodes=move(in);\n\t\treturn node;\n\t}\n\t\n\tstring getString();\n\t\n\tAstNode makeCopy(bool copyCache)\n\t{\n\t\tauto out=new AstTuple;\n\t\tcopyToNode(out, copyCache);\n\t\tfor (int i=0; i<(int)nodes.size(); i++)\n\t\t{\n\t\t\tout->nodes.push_back(nodes[i]->makeCopy(copyCache));\n\t\t}\n\t\treturn AstNode(out);\n\t}\n\t\n\t//void resolveReturnType();\n\t\n\tvoid resolveAction();\n\t\n\tToken getToken() {return nodes.empty()?nullptr:nodes[0]->getToken();}\n\t\nprivate:\n\t\n\tvector<AstNode> nodes;\n};\n\nclass AstType: public AstNodeBase\n{\npublic:\n\tbool isType() {return true;}\n\t\n\tvoid resolveAction()\n\t{\n\t\tthrow PineconeError(\"AstType::resolveAction called, which it shouldn't have been\", INTERNAL_ERROR, getToken());\n\t}\n};\n\nclass AstTypeType: public AstType\n{\npublic:\n\t\n\tstatic unique_ptr<AstTypeType> make(Type typeIn)\n\t{\n\t\tunique_ptr<AstTypeType> node(new AstTypeType);\n\t\tnode->returnTypeNotMeta=typeIn;\n\t\treturn node;\n\t}\n\t\n\tstring getString()\n\t{\n\t\treturn returnType->getString();\n\t}\n\t\n\tAstNode makeCopy(bool copyCache)\n\t{\n\t\tauto out=new AstTypeType;\n\t\tcopyToNode(out, copyCache);\n\t\tout->returnType=returnType;\n\t\treturn AstNode(out);\n\t}\n\t\n\tvoid resolveReturnType()\n\t{\n\t\treturnType=returnTypeNotMeta->getMeta();\n\t}\n\t\n\tvoid nameHintSet()\n\t{\n\t\tif (!nameHint.empty() && returnTypeNotMeta->nameHint.empty())\n\t\t\treturnTypeNotMeta->nameHint=nameHint;\n\t}\n\t\n\tToken getToken() {return nullptr;}\n\t\nprivate:\n\t\n\tType returnTypeNotMeta;\n};\n\nclass AstVoidType: public AstType\n{\npublic:\n\t\n\tstatic unique_ptr<AstVoidType> make()\n\t{\n\t\tunique_ptr<AstVoidType> node(new AstVoidType);\n\t\treturn node;\n\t}\n\t\n\tstring getString() {return \"{}\";}\n\t\n\tAstNode makeCopy(bool copyCache)\n\t{\n\t\tauto out=new AstVoidType;\n\t\tcopyToNode(out, copyCache);\n\t\treturn AstNode(out);\n\t}\n\t\n\tvoid resolveReturnType()\n\t{\n\t\treturnType=Void->getMeta();\n\t}\n\t\n\tToken getToken() {return nullptr;}\n\t\nprivate:\n};\n\nclass AstTokenType: public AstType\n{\npublic:\n\t\n\tstatic unique_ptr<AstTokenType> make(Token tokenIn)\n\t{\n\t\tunique_ptr<AstTokenType> node(new AstTokenType);\n\t\tnode->token=tokenIn;\n\t\treturn node;\n\t}\n\t\n\tstring getString();\n\t\n\tAstNode makeCopy(bool copyCache)\n\t{\n\t\tauto out=new AstTokenType;\n\t\tcopyToNode(out, copyCache);\n\t\tout->token=token;\n\t\treturn AstNode(out);\n\t}\n\t\n\tvoid resolveReturnType();\n\t\n\tToken getToken() {return token;}\n\t\nprivate:\n\t\n\tToken token=nullptr;\n};\n\nclass AstTupleType: public AstType\n{\npublic:\n\t\n\tstruct NamedType\n\t{\n\t\tToken name; // can be null\n\t\tunique_ptr<AstType> type;\n\t};\n\t\n\tstatic unique_ptr<AstTupleType> make(vector<NamedType>& in)\n\t{\n\t\tunique_ptr<AstTupleType> node(new AstTupleType);\n\t\tnode->subTypes=move(in);\n\t\treturn node;\n\t}\n\t\n\tstring getString();\n\t\n\tAstNode makeCopy(bool copyCache)\n\t{\n\t\tauto out=new AstTupleType;\n\t\tcopyToNode(out, copyCache);\n\t\tfor (int i=0; i<(int)subTypes.size(); i++)\n\t\t{\n\t\t\tout->subTypes.push_back({subTypes[i].name, unique_ptr<AstType>((AstType*)subTypes[i].type->makeCopy(copyCache).release())});\n\t\t}\n\t\treturn AstNode(out);\n\t}\n\t\n\tvoid resolveReturnType();\n\t\n\tToken getToken() {return subTypes.empty()?nullptr:subTypes[0].name;}\n\t\nprivate:\n\t\n\tvector<NamedType> subTypes;\n};\n\nclass AstActionWrapper: public AstNodeBase\n{\npublic:\n\t\n\tstatic unique_ptr<AstActionWrapper> make(Action actionIn) {\n\t\tauto out = unique_ptr<AstActionWrapper>(new AstActionWrapper);\n\t\tout->inLeftType=actionIn->getInLeftType();\n\t\tout->inRightType=actionIn->getInRightType();\n\t\tout->returnType=actionIn->getReturnType();\n\t\tout->action=actionIn;\n\t\tout->dynamic=true; // shouldn't matter\n\t\tout->ns=nullptr; // shouldn't matter\n\t\tout->inputHasBeenSet=true;\n\t\treturn out;\n\t}\n\t\n\tstring getString() {return \"action wrapper node\";}\n\t\n\tAstNode makeCopy(bool copyCache)\n\t{\n\t\tauto out=new AstActionWrapper;\n\t\tcopyToNode(out, true);\n\t\treturn AstNode(out);\n\t}\n\t\n\tvoid resolveAction()\n\t{\n\t\tthrow PineconeError(\"AstActionWrapper::resolveAction called, which it shouldn't have been\", INTERNAL_ERROR);\n\t}\n\t\n\tToken getToken() {return nullptr;}\n};\n\nclass AstWhatevToActionFactory: public AstNodeBase\n{\npublic:\n\t\n\tstatic AstNode make(function<Action(Type left, Type right)> lambda)\n\t{\n\t\tauto node=new AstWhatevToActionFactory();\n\t\tnode->lambda=lambda;\n\t\treturn AstNode(node);\n\t}\n\t\n\tstring getString() {return \"AstWhatevToActionFactory\";}\n\t\n\tAstNode makeCopy(bool copyCache)\n\t{\n\t\tauto out=new AstWhatevToActionFactory;\n\t\tcopyToNode(out, copyCache);\n\t\tout->lambda=lambda;\n\t\treturn AstNode(out);\n\t}\n\t\n\tvoid resolveAction() {throw PineconeError(\"AstWhatevToActionFactory::resolveAction called, wich should never happen\", INTERNAL_ERROR);}\n\t\n\tAstNode makeCopyWithSpecificTypes(Type leftInType, Type rightInType)\n\t{\n\t\tauto action=lambda(leftInType, rightInType);\n\t\tif (action)\n\t\t\treturn AstActionWrapper::make(action);\n\t\telse\n\t\t\treturn nullptr;\n\t}\n\t\n\tToken getToken() {return nullptr;}\n\t\n\tbool canBeWhatev() {return true;}\n\t\nprivate:\n\tfunction<Action(Type leftInType, Type rightInType)> lambda;\n};\n\n\n\n\n\n\n\n"
  },
  {
    "path": "h/CppProgram.h",
    "content": "#pragma once\n\n#include \"Type.h\"\n\n#include <map>\n\n#include <unordered_set>\n\n// Pinecone names that are hardcoded should start with '-' so that collisions can't happen with input code\n\n/* naming conventions for hardcoded Pineocne name prefixes\nthese go in frount of any names that are hardcoded for the transpiler, since they are not valid identifier\ncars they can not collide with names from pn source and they will be removed before they get to C++ source\n\nglobal funcs: $\nglobal vars: *\nlocal vars: -\ntypes: surounded by {}\n\n*/\n\nclass CppNameContainer\n{\npublic:\n\tstatic shared_ptr<CppNameContainer> makeRoot();\n\tshared_ptr<CppNameContainer> makeChild();\n\tvoid addPn(const string& pn, const string& cppNameHint=\"<- the value of that pn string please\"); // will throw an error if pnName already exists\n\tvoid reserveCpp(const string& cpp, bool ignoreCollisions=false);\n\tbool hasPn(const string& pn);\n\tstring getCpp(const string& pn); // will throw an error if the Pinecone name doesn't exist\n\tCppNameContainer* getParent() {return parent;}\n\t\nprivate:\n\t\n\tbool hasPnMe(const string& pn);\n\tCppNameContainer();\n\tbool hasCpp(const string& cpp);\n\tbool hasCppMe(const string& cpp);\n\tbool hasCppUp(const string& cpp);\n\tbool hasCppDown(const string& cpp);\n\t\n\tstd::unordered_set<string> cppSet;\n\tstd::map<string, string> pnToCppMap;\n\tCppNameContainer* parent=nullptr;\n\tvector<shared_ptr<CppNameContainer>> children;\n};\n\nclass CppFuncBase\n{\npublic:\n\tCppFuncBase(string prototypeIn, shared_ptr<CppNameContainer> myNames, bool returnsValIn);\n\t\n\tvoid code(const string& in);\n\tvoid name(const string& in); // converts a Pinecone name to a posibly different C++ name\n\tvoid line(const string& in);\n\tvoid endln();\n\tvoid comment(const string& in);\n\tvoid pushExpr();\n\tvoid popExpr();\n\tvoid pushBlock();\n\tvoid popBlock();\n\tstring pnToCpp(const string& in);\n\tint getExprLevel() {return exprLevel;}\n\tbool getIfFreshLine() {return freshLine;}\n\tint getBlockLevel() {return blockLevel;}\n\tbool getIfReturnsVal() {return returnsVal;}\n\t\n\tstring getSource() {return source;}\n\tstring getPrototype() {return prototype;}\n\t\nprivate:\n\tstring indent=\"\\t\";\n\tbool freshLine=true;\n\tint blockLevel=0;\n\tint exprLevel=0;\n\t\n\tstring varDeclareSource;\n\tstring source;\n\tstring prototype;\n\tbool returnsVal=false;\n\tbool fakeStartBlock=false;\n\t\n\tvector<shared_ptr<CppNameContainer>> namespaceStack;\n\t\n\tfriend CppProgram;\n};\n\ntypedef shared_ptr<CppFuncBase> CppFunc;\n\nclass CppProgram\n{\npublic:\n\t\n\tCppProgram();\n\t\n\tvoid code(const string& in)\t\t{activeFunc->code(in);}\n\tvoid name(const string& in)\t\t{activeFunc->name(in);}\n\tvoid line(const string& in)\t\t{activeFunc->line(in);}\n\tvoid endln()\t\t\t\t\t{activeFunc->endln();}\n\tvoid comment(const string& in)\t{activeFunc->comment(in);}\n\tvoid pushExpr()\t\t\t\t\t{activeFunc->pushExpr();}\n\tvoid popExpr()\t\t\t\t\t{activeFunc->popExpr();}\n\tvoid pushBlock()\t\t\t\t{activeFunc->pushBlock();}\n\tvoid popBlock()\t\t\t\t\t{activeFunc->popBlock();}\n\tstring pnToCpp(const string& in){return activeFunc->pnToCpp(in);}\n\tint getExprLevel()\t\t\t\t{return activeFunc->getExprLevel();}\n\tint getBlockLevel()\t\t\t\t{return activeFunc->getBlockLevel();}\n\tint getIfReturnsVal()\t\t\t{return activeFunc->getIfReturnsVal();}\n\t\n\t\n\tvoid setup();\n\tstring getTypeCode(Type in);\n\tvoid declareVar(const string& nameIn, Type typeIn, string initialValue=\"\");\n\tvoid declareGlobal(const string& nameIn, Type typeIn, string initialValue=\"\");\n\tvoid addHeadCode(const string& code);\n\tbool hasFunc(const string& name);\n\tvoid addFunc(const string& name, vector<std::pair<string, string>> args, string returnType, string contents);\n\tvoid pushFunc(const string& name, const string& cppNameHint, Type leftIn, Type rightIn, Type returnType);\n\tvoid pushFunc(const string& name, Type leftIn, Type rightIn, Type returnType) {pushFunc(name, name, leftIn, rightIn, returnType);}\n\t//void pushFunc(const string&, vector<NamedType> args, Type returnType);\n\tvoid popFunc();\n\tbool isMain() {return funcStack.size()==1;}\n\t\n\tstring getCppCode();\n\t\n\tshared_ptr<CppNameContainer> getGlobalNames() {return globalNames;};\n\t\nprivate:\n\t\n\tstring indent=\"\\t\";\n\tstring globalTopCode;\n\tstring globalIncludesCode;\n\tstring globalVarCode;\n\tstring globalTypesCode;\n\tCppFunc activeFunc;\n\tvector<string> funcStack;\n\tstd::map<string, CppFunc> funcs;\n\tshared_ptr<CppNameContainer> globalNames;\n};\n\nvoid addToProgPnStr(CppProgram * prog);\n\n"
  },
  {
    "path": "h/ErrorHandler.h",
    "content": "#pragma once\n\n#include \"Token.h\"\n\n#include <string>\nusing std::string;\n\n#define FUNC string(__FUNCTION__)\n//#define FUNC string(__PRETTY_FUNCTION__) //like __FUNCTION__, but adds class name\n\nenum ErrorPriority\n{\n\tSOURCE_ERROR,\n\tSOURCE_WARNING,\n\tJSYK,\n\tINTERNAL_ERROR,\n\tRUNTIME_ERROR\n};\n\nclass ErrorHandler\n{\npublic:\n\t\n\tstatic string priorityToStr(ErrorPriority in);\n\t\n\tvoid log(string msg, ErrorPriority priority, Token token=nullptr);\n\t\n\tvoid msg(string in);\n\t\n\tbool getIfErrorLogged() {return errorHasBeenLogged;}\n\t\nprivate:\n\t\n\tbool errorHasBeenLogged=false;\n};\n\nextern ErrorHandler error;\n\nclass PineconeError\n{\npublic:\n\tPineconeError(string msgIn, ErrorPriority priorityIn, Token tokenIn=nullptr);\n\t\n\tvoid log();\n\t\nprivate:\n\tstring msg;\n\tErrorPriority priority;\n\tToken token;\n\t\n};\n\n//typedef shared_ptr<PineconeError> Err;\n\n//Err makeError(string msgIn, ErrorPriority priorityIn, Token tokenIn=nullptr) {return Err(new PineconeError(msgIn, priorityIn, tokenIn));}\n"
  },
  {
    "path": "h/Namespace.h",
    "content": "#pragma once\n\n#include \"Type.h\"\n#include \"Action.h\"\n#include \"Token.h\"\n#include \"Operator.h\"\n#include \"AstNode.h\"\n\n#include <unordered_map>\nusing std::unordered_map;\n\n#include <vector>\nusing std::vector;\n\nclass StackFrame;\n\nclass NamespaceData;\ntypedef shared_ptr<NamespaceData> Namespace;\n\n/// has a bunch of hash tables for all the identifiers in a single scope\n// contains a pointer to a stack frame but there may be many namespaces (due to many scopes) in a single stack frame\n//  for example, a function has a single stack frame but has several if blocks, each with its own NamespaceData\n//  each NamespaceData also has a pointer to its parent, which should only be null for the global standard library\n// contains a pointer to its parent namespace, which can be null if it is the root\n// can be created with one of the 'make' functions, not by directly instantiating it\nclass NamespaceData: public std::enable_shared_from_this<NamespaceData>\n{\npublic:\n\t\n\t// makes a namespace with no parents and a new stack frame\n\tstatic Namespace makeRootNamespace();\n\t\n\t// makes a child namespace with the same stack frame as this one\n\tNamespace makeChild();\n\t\n\t// makes a child namespace with a new stack frame\n\tNamespace makeChildAndFrame(string nameIn);\n\t\n\t// returns a string with the complete contents of this namespace\n\tstring getString();\n\t\n\t// retuens a string with this namespace and all it's parents nicely formatted\n\tstring getStringWithParents();\n\t\n\t//Namespace getParent() {return parent;}\n\tshared_ptr<StackFrame> getStackFrame() {return stackFrame;}\n\t\n\tvoid setInput(Type left, Type right);\n\tvoid addNode(AstNode node, string id);\n\t\n\t// recursivly searches up looking for a type of the given name\n\t// returns UnknownType if it cant find the requested type\n\tType getType(string name, bool throwSourceError, Token tokenForError);\n\t\n\t// returns the destructor of the given type, or nullptr if there isn't one\n\tAction getDestroyer(Type type);\n\t\n\t// returns the copier of the given type, or nullptr if there isn't one\n\tAction getCopier(Type type);\n\t\n\t// returns an action that takes the input types\n\t// on error, it will throw a source error if throwSourceError is true. otherwise, it will return nullptr\n\tAction getActionForTokenWithInput(Token token, Type left, Type right, bool dynamic, bool throwSourceError, Token tokenForError);\n\t\n\tvector<Action>* getDestroyerActions() {return &destructorActions;}\n\tAction wrapInDestroyer(Action in);\n\t\nprivate:\n\t\n\t// retrieve all nodes in the given catagories with the given names from this namespace and all its parents\n\tvoid getNodes(vector<AstNodeBase*>& out, string text, bool checkActions, bool checkDynamic, bool checkWhatev);\n\t\n\tvoid nodesToMatchingActions(vector<Action>& out, vector<AstNodeBase*>& nodes, Type leftInType, Type rightInType);\n\t\n\tclass IdMap\n\t{\n\tpublic:\n\t\tvoid add(string key, AstNode node);\n\t\tvoid get(string key, vector<AstNodeBase*>& out);\n\t\t\n\tprivate:\n\t\tunordered_map<string, vector<AstNode>> nodes;\n\t};\n\t\n\t// add a get and set action for a variable also adds its data to the stack frame\n\tAction addVar(Type type, string name);\n\t\n\t// the only constructor, is private so use a make function instead\n\tNamespaceData(Namespace parentIn, shared_ptr<StackFrame> stackFrameIn, string nameIn=\"\");\n\t\n\t// the name of this namespace, for debugging purposes only\n\tstring myName;\n\t\n\t// this namespaces parent\n\tshared_ptr<NamespaceData> parent;\n\t\n\t// the stack frame this namespace uses\n\t// \tdoes not have a reference back because there can be many namespaces in one stack frame\n\tshared_ptr<StackFrame> stackFrame;\n\t\n\t// contains all actions that can be used anywhere, and don't rely on dynamic content like variables\n\tIdMap actions;\n\t\n\t// contains actions that use runtime data, like variables\n\tIdMap dynamicActions;\n\t\n\t// contains actions that use a whatev type\n\tIdMap whatevActions;\n\t\n\t// contains all types in this namespace\n\tIdMap types;\n\t\n\t// contains destructors for types, the key string is a pointer to the type fed through ptrToUniqueStr with 6 digits\n\t//IdMap destructors;\n\t\n\t// like destructors, but for making copies\n\t//IdMap copiers;\n\t\n\tvector<Action> destructorActions;\n};\n\n"
  },
  {
    "path": "h/Operator.h",
    "content": "#pragma once\n\nclass TokenData;\n\n#include <memory>\nusing std::shared_ptr;\n\n#include <string>\nusing std::string;\n\nclass AllOperators;\n\n// describes an operator\n// NOTE: there will only be one instance of OperatorData for +, not one for every overload of +\nclass OperatorData\n{\npublic:\n\t\n\tenum InputTaken\n\t{\n\t\tLEFT,\n\t\tRIGHT,\n\t\tBOTH,\n\t};\n\t\n\tstring getText() {return text;}\n\tint getPrecedence() {return precedence;}\n\tbool isOverloadable() {return overloadable;}\n\tbool takesLeftInput() {return input==BOTH || input==LEFT;}\n\tbool takesRightInput() {return input==BOTH || input==RIGHT;}\n\t\nprivate:\n\t\n\tfriend AllOperators;\n\t\n\tOperatorData(string textIn, int precedenceIn, InputTaken inputIn, bool overloadableIn)\n\t{\n\t\ttext=textIn;\n\t\tprecedence=precedenceIn;\n\t\tinput=inputIn;\n\t\toverloadable=overloadableIn;\n\t}\n\t\n\t// the text of the operator, generally 1 or 2 characters\n\tstring text;\n\t\n\t// the precedence of left and right inputs, if this is 0 then the operator does not take an input on that side\n\t// if even then precedence level is parced left to right. if odd then right to left\n\tint precedence;\n\t\n\t// if this operator can be overloaded\n\tbool overloadable;\n\t\n\t// if this operator takes input from the left, right or both\n\tInputTaken input;\n};\n\ntypedef shared_ptr<OperatorData> Operator;\n\n"
  },
  {
    "path": "h/PineconeProgram.h",
    "content": "#pragma once\n\n#include \"VERSION.h\"\n\n#include <string>\n#include <iostream>\n#include <math.h>\n#include <vector>\n#include <list>\n\nusing std::max;\nusing std::min;\nusing std::cout;\nusing std::endl;\nusing std::string;\nusing std::to_string;\nusing std::vector;\nusing std::list;\n\n#include \"msclStringFuncs.h\"\n#include \"Namespace.h\"\n#include \"StackFrame.h\"\n#include \"Token.h\"\n#include \"AstNode.h\"\n#include \"SourceFile.h\"\n\nextern vector<string> cmdLineArgs;\n\nclass Element;\n\nclass PineconeProgram\n{\npublic:\n\t\n\tPineconeProgram();\n\t~PineconeProgram() {cleanUp();}\n\t\n\tstring getCpp();\n\t\n\tvoid resolveProgram(string inFilename, bool printExtraOutput);\n\t\n\tNamespace getGlobalActionTable();\n\t\n\tvoid execute();\n\t\nprivate:\n\t\n\tvoid cleanUp();\n\t\nprivate:\n\t\n\tshared_ptr<SourceFile> file=nullptr;\n\t\n\t//a list of all the tokens in the program\n\tvector<Token> tokens;\n\t\n\t//root of the abstract syntax tree\n\tAstNode astRoot=nullptr;\n\t\n\t//root of the action tree\n\tAction actionRoot=createNewVoidAction();\n\t\n\tvector<char> whitespaceChars, letterChars, digitChars;\n\tchar singleLineComment;\n};\n\n"
  },
  {
    "path": "h/SourceFile.h",
    "content": "#pragma once\n\n#include <string>\nusing std::string;\n\nclass SourceFile\n{\npublic:\n\t\n\tSourceFile()\n\t{\n\t\tfilename=\"[empty_file]\";\n\t\tcontents=\"\";\n\t}\n\t\n\tSourceFile(string filenameIn, bool printOutput);\n\t\n\tstring getFilename() {return filename;}\n\t\n\t// get the path to the directory this file is in\n\tstring getDirPath();\n\t\n\tconst string& getContents() {return contents;}\n\t\n\tstring getBoxedString();\n\t\n\tstring getLine(int lineNum);\n\t\n\tinline int size()\n\t{\n\t\treturn contents.size();\n\t}\n\t\n\tinline char operator[](int i)\n\t{\n\t\treturn contents[i];\n\t}\n\t\n\tinline string substr(size_t start, size_t len)\n\t{\n\t\treturn contents.substr(start, len);\n\t}\n\t\nprivate:\n\t\n\tstring filename;\n\tstring contents;\n};\n"
  },
  {
    "path": "h/StackFrame.h",
    "content": "#pragma once\n\n#include <vector>\nusing std::vector;\n\n#include \"Type.h\"\n//#include \"Action.h\"\n\nextern void* globalFramePtr;\nextern void* stackPtr;\n\nclass StackFrame\n{\npublic:\n\tvoid addMember(Type in);\n\t\n\t//\tset the left and right input types (can only be done once)\n\tvoid setInput(Type left, Type right);\n\t\n\tsize_t getSize() {return frameSize;}\n\tType getLeftInType();\n\tType getRightInType();\n\tsize_t getLeftOffset();\n\tsize_t getRightOffset();\n\t\nprivate:\n\t\n\t//Action actions; //must always be functionAction\n\tvector<Type> members;\n\tsize_t frameSize=0;\n\tbool inputSet=false;\n\tint leftInputIndex=-1;\n\tint rightInputIndex=-1;\n\tsize_t leftInputOffset;\n\tsize_t rightInputOffset;\n};\n"
  },
  {
    "path": "h/Token.h",
    "content": "#pragma once\n\n#include \"Operator.h\"\n\n#include <string>\nusing std::string;\n\n#include <vector>\nusing std::vector;\n\nclass SourceFile;\n\n//represents a single token such as an Int literal, an operator, or an identifier\n//is immutable\nclass TokenData\n{\npublic:\n\t\n\tenum Type\n\t{\n\t\tWHITESPACE,\n\t\tLINE_END,\n\t\tIDENTIFIER,\n\t\tLITERAL,\n\t\tSTRING_LITERAL,\n\t\tOPERATOR,\n\t\tLINE_COMMENT,\n\t\tBLOCK_COMMENT,\n\t\tSCOPE,\n\t\tCAST,\n\t\tTUPLE,\n\t\tUNKNOWN\n\t};\n\t\n\tTokenData(string textIn, shared_ptr<SourceFile> fileIn, int lineIn, int charPosIn, Type tokenTypeIn, Operator opIn=Operator(nullptr))\n\t{\n\t\ttext=textIn;\n\t\tfile=fileIn;\n\t\tline=lineIn;\n\t\tcharPos=charPosIn;\n\t\ttokenType=tokenTypeIn;\n\t\top=opIn;\n\t}\n\t\n\tstring getText() const {return text;}\n\tshared_ptr<SourceFile> getFile() const {return file;}\n\tint getLine() const {return line;}\n\tint getCharPos() const {return charPos;}\n\tTokenData::Type getType() const {return tokenType;}\n\tOperator getOp() const {return op;}\n\tbool isComment() {return tokenType==LINE_COMMENT || tokenType==BLOCK_COMMENT;}\n\t\n\tstatic string typeToString(TokenData::Type in);\n\tstring getDescription();\n\tstring getTypeDescription();\n\t\nprivate:\n\t\n\tstring text;\n\tshared_ptr<SourceFile> file;\n\tint line;\n\tint charPos;\n\tType tokenType;\n\tOperator op;\n};\n\ntypedef shared_ptr<TokenData> Token;\n\nToken makeToken(string textIn, shared_ptr<SourceFile> fileIn, int lineIn, int charPosIn, TokenData::Type tokenTypeIn, Operator opIn=Operator(nullptr));\nToken makeToken(string textIn);\n\nstring stringFromTokens(const vector<Token>& tokens, int left, int right);\nstring tableStringFromTokens(const vector<Token>& tokens, string tableName);\n"
  },
  {
    "path": "h/Type.h",
    "content": "#pragma once\n\n#include <string>\nusing std::string;\n\n#include <vector>\nusing std::vector;\n\n#include <memory>\nusing std::shared_ptr;\nusing std::unique_ptr;\n\n#include <cstring>\nusing std::memcpy;\n\nclass TypeBase;\n\ntypedef shared_ptr<TypeBase> Type;\n\nconst extern Type Unknown;\nconst extern Type Whatev;\nconst extern Type Void;\nconst extern Type Bool;\nconst extern Type Byte;\nconst extern Type Int;\nconst extern Type Dub;\nextern Type String;\n\nclass CppProgram;\nclass ActionData;\n\nstruct NamedType\n{\n\tstring name;\n\tType type;\n};\n\nstruct OffsetAndType\n{\n\tsize_t offset;\n\tType type;\n};\n\nclass TypeBase: public std::enable_shared_from_this<TypeBase>\n{\npublic:\n\n\tvirtual ~TypeBase() = default;\n\t\n\t///steps to adding a new type (these may be old):\n\t///\t1. Add to the enum\n\t///\t2. add it to toString in Type.cpp\n\t///\t3. add it to isCreatable in Type.cpp\n\t///\t4. if it has a literal, add a class for that in LiteralElement.h\n\t/// 5. add the creation of said literal to LiteralElement::makeNew in LiteralElement.cpp\n\t///\t6. you may have to add logic to initialProgramPopulation or getElementType to correctly capture the section of source containing your type literal\n\t///\t7. add a class to DataElem.h\n\t/// 8. add it to makeNewOfType in DataElem.cpp\n\t\n\tenum PrimitiveType\n\t{\n\t\tUNKNOWN ,\n\t\tVOID ,\n\t\tBYTE,\n\t\tDUB,\n\t\tINT,\n\t\tPTR,\n\t\tBOOL,\n\t\tTUPLE,\n\t\tWHATEV,\n\t\tMETATYPE,\n\t};\n\t\n\t/* type compact forms\n\tVoid: v\n\tUnknown: u\n\tBool: b\n\tByte: y\n\tInt: i\n\tDub: d\n\tPtr: Pp_..._pP\n\tTuple: Tt_[size of name]_name_type..._tT\n\tWhatev: W\n\tMeta: Mm_..._mM\n\t*/\n\t\n\tstatic Type makeNewVoid();\n\tstatic Type makeNewPrimitive(PrimitiveType typeIn);\n\tstatic Type makeNewWhatev();\n\t//static Type makeNew(unordered_map<string, Type>, string nameIn);\n\t\n\t//TypeBase(string nameIn) {name=nameIn;}\n\t\n\tType getMeta();\n\tType getPtr();\n\tvirtual Type actuallyIs(Type target); // returns a type with with the whatevs resolved with the target type\n\t\n\tstatic string getString(PrimitiveType in);\n\tvirtual string getString()=0;\n\tstring getName() {return nameHint.empty()?getCompactString():nameHint;}\n\tvirtual string getCompactString()=0; // returns a string that is unique, only shared with other types that match this one\n\tvirtual string getCppLiteral(void * data, CppProgram * prog)=0;\n\t\n\tvirtual bool isCreatable() {return true;};\n\tvirtual bool isVoid() {return false;};\n\tvirtual bool isWhatev() {return false;};\n\t\n\tvirtual size_t getSize()=0;\n\t//string getName() {return name;}\n\t\n\tvirtual PrimitiveType getType()=0;\n\t\n\tbool matches(Type other);\n\t\n\tvirtual Type getSubType() {return Void;}\n\tvirtual OffsetAndType getSubType(string name) {return {0, nullptr};}\n\t\n\tvirtual vector<NamedType>* getAllSubTypes(); // will thow an error if this is not a tuple type\n\t\n\t// void setNameHint(const string& in) {if (nameHint.empty()) nameHint=in;} // only sets name hint on any type once, after that it fails quietly\n\t// string getNameHint\n\t\n\tstring nameHint=\"\"; // not reliable, will often be \"\"; should only be used as a hint, not depended on\n\t\nprotected:\n\t\n\tvirtual bool matchesSameTypeType(Type other)=0;\n\t\n\tType ptrToMe=nullptr;\n};\n\nType makeTuple(const vector<NamedType>& in, bool isAnonymous);\n\n//\tsince types are immutable, this class is an easy way to construct a tuple type\nclass TupleTypeMaker\n{\npublic:\n\tTupleTypeMaker();\n\tvoid add(string name, Type type);\n\n\tvoid add(Type type);\n\t\n\tType get(bool isAnonymous);\n\t\nprivate:\n\t\n\tstring getUniqueName();\n\t\n\tstd::unique_ptr<vector<NamedType>> subTypes;\n};\n"
  },
  {
    "path": "h/VERSION.h",
    "content": "#pragma once\n\n// the version of pinecone is vX.Y.Y\n\nconst int VERSION_X=0;\nconst int VERSION_Y=5;\nconst int VERSION_Z=1;\n"
  },
  {
    "path": "h/msclStringFuncs.h",
    "content": "#pragma once\n\n#include \"PineconeProgram.h\"\n\n#include <string>\nusing std::string;\nusing std::to_string;\n\n#include <vector>\nusing std::vector;\n\n#include <functional>\nusing std::string;\n\n#include \"utils/stringUtils.h\"\n\n//\treturns if the substring matches the input\n//\tnothing needed for unicode\n//\t\tin: the string to check against\n//\t\tpos: the location in 'in' to line the start of the substring up with\n//\t\tsubStr: the string to compare with\n//\t\treturns: if the substring matches the input at the given location\nbool substringMatches(const string& in, int pos, const string& subStr);\n\n//\treturns the location of a pattern in a string, or -1 if it can't find it\n//\tno unicode support yet\n//\t\tin: the string to search\n//\t\tstartPos: where to start looking (inclusive)\n//\t\tpattern: the single or multi character pattern to search for, wildcards are not yet supported\n//\t\treturns: the absolute position (not the offset) of the first instance of the pattern in the input, or -1 if it can't find it\nint searchInString(const string& in, const string& pattern, int startPos=0);\n\n//\treplaces all instances of one substring with another\n//\t\tin: the string to search\n//\t\tsearchFor: pattern to replace\n//\t\treplaceWith: new value\n//\t\treturns: in after replace operation\nstring replaceSubstring(const string& in, const string& searchFor, const string& replaceWith);\n\n//\tsets the given array to be the given string sliced up using the given pattern\n//\t\tin: the string to slice\n//\t\tpattern: the pattern used to chop up the string, will not be included in output\n//\t\tout: all the substrings will be appended to this\nvoid sliceStringBy(const string& in, const string& pattern, vector<string>& out);\n\n//\tindents a string\n//\t\tin: the string to indent (can be multi line)\n//\t\tindent: the string to use as the indent\n//\t\treturns: the string indented\nstring indentString(const string& in, string indent=\"    \", int level=1);\n\n//\treturns the original string with the tabs replaced by the correct number of spaces\n//\t\tin: the string to convert\n//\t\tspaceNum: number of spaces per tab\n//\t\treturns: a string with the tabs replaced by spaces\nstring tabsToSpaces(const string& in, int spaceNum=4);\n\n//\truns tabsToSpaces on an entire array of strings\nvoid tabsToSpaces(vector<string>& in);\n\n//\treturns the original string but padded with the given padding string\n//\t\tin: the string to pad\n//\t\tsize: the size of the output string\n//\t\talignment:\n//\t\t\t1: left\n//\t\t\t-1: right\n//\t\t\t0: center\n//\t\tpad: the string to use for padding (assumes this string is one char long)\n//\t\tleftCap: a string to put on the left size of the input (inside the padding) that will not get chopped\n//\t\trightCap: a string to put on the right size of the input (inside the padding) that will not get chopped\n//\t\treturns: the padded string, or the chopped string if the input is shorter then the size\nstring padString(const string& in, int size, int alignment=1, string pad=\" \", string leftCap=\"\", string rightCap=\"\");\n\n//\treturns the specific line (starting at 1) in the string it is sent\n//\t\tin: the (presumably multiline) string\n//\t\tlineNum: the line to return\n//\t\treturns: the specific line (without newlines), or an empty string if that line is invalid\nstring getTextOfLine(const string& in, int lineNum);\n\n//\ttakes an array of lines and puts a box around it\n//\t\tin: an array of strings, each which will be on a new line\n//\t\tboxName: the name of the box\n//\t\tlineNum: the offset of line numbers, no line nums will be displayed if -1\n//\t\talwaysWidthMax: if to always use the max width\n//\t\tmaxWidth: the max width of a line, will be truncated if longer\n//\t\treturns: a string with a box around the content (must be displayed in monospace obviously)\nstring lineListToBoxedString(const vector<string>& in, string boxName=\"\", int lineNum=-1, bool alwaysWidthMax=false, int maxWidth=-1);\n\n//\tputs the contents of a string into a well formatted\n//\t\tin: the input stringz\n//\t\tboxName: the name that will appear at the top of the box\n//\t\tshowLineNums: if to show line numbers\n//\t\talwaysWidthMax: if to always use the max width\n//\t\tmaxWidth: the maximum width of the contents of the box (with borders it may be a bit wider), if any line is longer it will be chopped\n//\t\treturns: the boxed string\nstring putStringInBox(const string& in, string boxName=\"\", bool showLineNums=false, bool alwaysWidthMax=false, int maxWidth=-1);\n\n//\tputs the contents of a string into a table, with tabs being verticle seporators and newlines being horizontle ones\n//\t\tin: the input string\n//\t\ttableName: the name that will apear at the top of the table\n//\t\treturns: a string that looks like a table\nstring putStringInTable(const string& in, string tableName);\n\n// assembles one section of a tree\nstring assembleTreeString(const string& root, vector<string>& leaves);\n\n//\tconverts a double to a string, with always at least one zero before and after the decimal\nstring doubleToString(double in);\n\nint stringToInt(string in);\n\ndouble stringToDouble(string in);\n\n//\tload entire file and return its contents\n//\t\tinName: the path to the file to open\n//\t\tdebug: if to print status several times to stdout\n//\t\treturns: the contents of the file, or an empty string if there is an error\nstring loadEntireFile(string inName, bool debug=false);\n\nbool writeFile(const string& filename, const string& contents, bool debug=false);\n\n// returns a random character that can be an upper case letter, a lower case letter or a digit\nchar getRandChar();\n\n// given a hint name and a function to check if a name is unique, returns a unique string\n// checker should return true if the given name IS valid\n// if alwaysAppendRandom, it will always append a number of random digits\nstring getUniqueString(string hint, std::function<bool (string)> checker, bool alwaysAppendRandom=false);\n\n//\trun a shell command and return the output\n//\t\tcmd: the command to run\n//\t\treturns: the output of the command\nstring runCmd(string cmd, bool printOutput=false);\n\n//\tget width of the current terminal\n//\t\treturns: width of the terminal\nint getTermWidth();\n"
  },
  {
    "path": "h/utils/fileUtils.h",
    "content": "\n#pragma once\n\n#include \"stringUtils.h\"\n\nvoid loadFile(string filepath, string& contents);\nvoid writeFile(string filepath, const string& contents);\n\n"
  },
  {
    "path": "h/utils/stringArray.h",
    "content": "#pragma once\n\n#include \"stringUtils.h\"\n\nnamespace str\n{\n\nvoid splitBy(vector<string>& out, const string& in, const string& splitter, bool keepSplitter=false);\n\n//void splitBy(vector<string>& out, const string& in, vector<string>& splitters, bool keepSplitter=false);\n\ninline void splitByLine(vector<string>& out, const string& in);\n\nint getMaxWidth(vector<string>& in);\n\n// if size is -1 then it is determined as the max width of all the elements in out\nvoid padWidths(vector<string>& out, int size=-1, StringPadAlignment alignment=ALIGNMENT_LEFT, string pad=\" \", string leftCap=\"\", string rightCap=\"\");\n\nstring join(vector<string>& in, string joiner=\"\\n\", bool addAtEnd=true);\n\n\n/// inline implementations\n\ninline void splitByLine(vector<string>& out, const string& in)\n{\n\tsplitBy(out, in, \"\\n\");\n}\n\n}\n\n"
  },
  {
    "path": "h/utils/stringDrawing.h",
    "content": "#pragma once\n\n#include \"stringUtils.h\"\n\nnamespace str\n{\n\n// if max width is -1, it will autodetect\nstring getBoxedString(const string& in, string boxName=\"\", bool showLineNums=false, bool alwaysWidthMax=false, int maxWidth=-1);\n\n// it is assumed that the data is already padded\nvoid putArrayInTreeNodeBox(vector<string>& data);\n\nstring putStringInTreeNodeBox(const string& in);\n\n// note that the input may have newlines in each element\nstring makeList(vector<string>& data);\n\nstring makeRootUpBinaryTree(const string& root, const string& leftBranch, const string& rightBranch, const string& leftLeaf, const string& rightLeaf);\n\n//string makeTreeSection(const string& root, vector<string>& leaves);\n\n}\n\n"
  },
  {
    "path": "h/utils/stringNumConversion.h",
    "content": "#pragma once\n\n#include \"stringUtils.h\"\n\nnamespace str\n{\n\n// returns an escape code that can be placed in a C++ string literal and will evaluate to the given char\nstring charToCppStringLiteralEscaped(unsigned char c);\n\n// returns a base number with 0-9 being 0-9, 10-35 being a-z and 36-61 being A-Z\n// if maxDigits is >=0 will return only the leftmost maxDigits\nstring intToBase62(unsigned int in, int maxDigits=-1);\n\n// uses intToBase62 to convert ptrIn to a string that can be used in a C++ id\nstring ptrToUniqueStr(void* ptrIn, int digits=4);\n\n}\n\n"
  },
  {
    "path": "h/utils/stringUtils.h",
    "content": "\n#pragma once\n\n/// This string util header will slowly replace msclStringFuncs.h\n\n#include <string>\nusing std::string;\n\n#include <vector>\nusing std::vector;\n\nnamespace str\n{\n\ninline void nextGlyph(int& out, const string& in);\n\ninline int getWidth(const string& in);\n\n// returns the byte location of the given glyph\ninline int seek(const string& in, int distGlyph, int startPosByte=0);\n\n// currently is a straight equals, but in the future could do things such as evaluate strings with different types of newlines to equal\ninline bool subMatches(const string& in, int posBytes, const string& sub);\n\n// if endGlyph is -1 it takes till the end of the string\ninline string sub(const string& in, int startGlyph, int endGlyph);\n\ninline bool matches(const string& a, const string& b);\n\ninline bool hasPrefix(const string& in, const string& prefix);\n\ninline bool hasSuffix(const string& in, const string& suffix);\n\n// returns the BYTE location (not glyph location), or -1 if pattern doesn't appear\n//int searchFor(const string& in, string pattern, int startByte);\n\n// returns the glyph position of the first occurrence of pattern, or -1 if it doesn't appear\nint getGlyphPosOf(const string& in, string pattern);\n\nstring tabsToSpaces(const string& in, int tabWidth=4);\n\nenum StringPadAlignment {ALIGNMENT_LEFT=1, ALIGNMENT_CENTER=0, ALIGNMENT_RIGHT=-1};\n\n// alignment: 1 = left, -1 = right, 0 = center\n// pad is assumed to be of width 1\nstring pad(const string& in, int size, StringPadAlignment alignment=ALIGNMENT_LEFT, string pad=\" \", string leftCap=\"\", string rightCap=\"\");\n\n\n/// inline implementations\n\ninline void nextGlyph(int& out, const string& in)\n{\n\tdo {\n\t\tout++;\n\t} while (out<(int)in.size() && (in[out] & 0x80) && !(in[out] & 0x40));\n}\n\ninline int getWidth(const string& in)\n{\n\tint glyphPos=0;\n\tint bytePos=0;\n\t\n\twhile (bytePos<(int)in.size())\n\t{\n\t\tnextGlyph(bytePos, in);\n\t\tglyphPos++;\n\t}\n\t\n\treturn glyphPos;\n}\n\ninline int seek(const string& in, int distGlyph, int startPosByte)\n{\n\tint i=startPosByte;\n\t\n\twhile (distGlyph>0)\n\t{\n\t\tnextGlyph(i, in);\n\t\t\n\t\tdistGlyph--;\n\t}\n\t\n\treturn i;\n}\n\ninline bool subMatches(const string& in, int posBytes, const string& sub)\n{\n\tif (posBytes<0  || sub.size()+posBytes>in.size())\n\t\treturn false;\n\t\n\tfor (int i=0; i<(int)sub.size(); i++)\n\t{\n\t\tif (in[i+posBytes]!=sub[i])\n\t\t\treturn false;\n\t}\n\t\n\treturn true;\n}\n\ninline string sub(const string& in, int startGlyph, int endGlyph)\n{\n\tint startByte=seek(in, startGlyph);\n\tint endByte=(endGlyph < 0 ? (int)in.size() : seek(in, endGlyph-startGlyph, startByte));\n\treturn in.substr(startByte, endByte-startByte);\n}\n\ninline bool matches(const string& a, const string& b)\n{\n\tif (a.size()!=b.size())\n\t\treturn false;\n\t\n\treturn subMatches(a, 0, b);\n}\n\ninline bool hasPrefix(const string& in, const string& prefix)\n{\n\treturn subMatches(in, 0, prefix);\n}\n\ninline bool hasSuffix(const string& in, const string& suffix)\n{\n\treturn subMatches(in, in.size()-suffix.size(), suffix);\n}\n\n}\n\n#include \"stringArray.h\"\n#include \"stringDrawing.h\"\n"
  },
  {
    "path": "other/pinecone.pn",
    "content": "\nprint: argLen.String + \" args:\"\n\ni: 0 | i < argLen | i: i + 1 @ (\n\tprint: arg: i\n)\n"
  },
  {
    "path": "other/pinecone_concept.txt",
    "content": "# Programming language concept by Sophie Winter\n# This is not ment to be actual code, just a place to exparament with different ideas of how the language might look\n\nadd={a=$ b=$ a+b}\n\na=7\nb=3\n\nz={sqrt(@)_}\n\nadd=z\n\nadd(&w &x w+x}, b)\n\nb==3?\n\tprint(\"yes\")\n:b==4?\n\tprint(\"4\")\n:{\n\tprint(z)\n\tadd()\n}\n\nprint(add(a))\n\nmax=\n{\n\ta,b,c=$\n\ta>b && a>c? a\n\t: b>c? b\n\t: c\n}\n\nmax=\n{\n\ta,b=$\n\ta>b?a:b\n}\n\n\nmax: a, b, c\n\nprint: \"hello world, the numer is \" 7\n\na>b?a,b\n\ncar.drive\n\n\"hello world\".print\n\n7,5.max\n\nb:7\ng:9.81\n\nstr:\"hello world\"\n\nzero:Int\n\n___________________________________________________\n\n\nmax$:\n{\n\tInt: z\n\t\n\t>.z\n}\n\n$func:\n{\n\ta,b:$(Dub, Dub)\n}\n\nfunc:\n{\n\ta:tru\n\tb:fls\n\t\n\ta?\n\t(\n\t\tprint: \"hello\"\n\t\t9\n\t),(\n\t\n\tb? print: \"world\"\n\t\n\t7)\n}\n\nfunc: (a: Int, b: Int):\n{\n\ta>b?\n\t\ta+=3,\n\t\t~b\n\t\n\ti: 0, i<6, i++ @\n\t(\n\t\tb--\n\t\t\n\t\tb<0?\n\t\t\t~7\n\t)\n}\n\n___________________________________________________\n\n\nin: {Int, Int}\nfuncs: {Dub, Dub}, {Int, Bool}\nout: error? #1?\n\nin: {Int, Int}\nfuncs: {Dub, Int}, {Int, Dub}\nout: error because tie\n\nin: {Int, Int}\nfuncs: {Int, Bool}, {Dub, Bool}\nout: #1\n\nin: {Int, Dub}\nfuncs: {Int, Int}, {Dub, Dub}\nout: #2\n\nin: {Bool, Bool}\nfuncs: {Int, Int}, {Dub, Dub}\nout: error because tie (only cares if more or less complex, not how much)\n\n___________________________________________________\n\n\nmax: {a: Int, b: Int}:\n\t~a>b?a|b\n\ni: 0..8@\n(\n\t\n)\n\n(i=0; i<b; ++i)\n{\n\t\n}\n\n___________________________________________________\n\n________\n_ ______\n_ _  ___\n4+a: 5+3\n\n     |\n    / \\\n   / / \\\n  / /  /\\\n / /  / /\\\n4+a: 5+b: 3\n\n___________________________________________________\n\n\na: 1 | a<100 | a++ @\n(\n\t\n)\n\nfunc: {}|&Int.{}:\n(\n\t#do stuff\n)\n\n\natan2: $Dub|{y: Dub, x: Dub}.\n[\n\t\n]\n\n\n\nang: (4, 5).atan2\n\n\natan2: {y: Dub; x: Dub}\n[\n\t\n]\n\n___________________________________________________\n\n\na[b]\n\n(a: (b))\n\ni: 100\n\n___________________________________________________\n\n\nfuncName:\n{\n\t^Int\n\ta: Dub\n\tb: Dub\n}[\n\ti: 10\n\t\n\t(\n\t\tj: 20\n\t\t^j\n\t)\n\t\n\t(\n\t\tj: 7\n\t\t^j\n\t)\n]\n\ndoStuff: {me: String}\n[\n\tval: Int: me\n\t\n\tval+: a\n\t\n\t^val\n]\n\n___________________________________________________\n\n\na: 8\n\na: 12\n\nb: a\n\nc: {a: Int}\n[\n\tc=0 ?\n\t\t~0\n\t|\n\t\t~c-1\n]\n\na: 2 + c: 3+4\n\n___________________________________________________\n\n\nif a\n(\n\t# code\n)\nelse\n(\t\n\t#[\n\t\tthis is a block comment\n\t#]\n)\n\n___________________________________________________\n\n\na: tru\nb: 9\n\nwhile a=tru\n(\n\tb-:1\n\t\n\tif b<0\n\t\ta: fls\n)\n\n5-3-2\n\na: b: c\n\n___________________________________________________\n\n\nprint: a\t# works because a is defined below\na:: 8\t\t# constant\na: 7\t\t# compile error\n\nprint: b\t# compile error\n$b: 8\t\t# variable\nb: 7 \t\t# works\n\nprint: c\t# compile error\n$c:: 8\t\t# immutable\nc: 7\t\t# compile error\n\n\nmyFunc :: {val1: Int; val2: Int}\n[\n\t\n]\n\n___________________________________________________\n\n\n\\+ :: {Int} < {a: Int}.{b: Int}\n[\n\ta+b^\n]\n\nfunc :: {me: Int | a: Dub} > {Int}\n[\n\t\n]\n\nfunc :: {me: Int}.{a: Dub} > {Int}\n[\n\t\n]\n\n___________________________________________________\n\n\\\\\nthis\nis\nblock\ncomment\n//\n\n\n//\nthis\nis\nblock\ncomment\n\\\\\n\n\\\\ it looks great on one line too //\n\n___________________________________________________\n\n\nBaseClass ::\n{\n\tfoo: Dub\n}\n\nMyObj ::\n{\n\t$super: BaseClass\n\ta: Int\n\tb: Int\n}\n\nMyObj :: {} > {MyObj}:\n(\n\treturn: (9.3), 8, 12\n)\n\naddToBoth :: {$me: MyObj}.{}:\n(\n\ta+: 1\n\tb+: 1\n\tfoo\n)\n\nmyPrint: tru, 12, 8.9\n\nobj: MyObj\n\nobj.addToBoth\n\n___________________________________________________\n\n\na: b: 7-1-1\n\n  :\n / \\\na   :\n   / \\\n  b   -\n\t / \\\n\t-   1\n   / \\\n  7   1\n\n\n___________________________________________________\n\na: {}\na.b: 8\na.c: \"hello\"\n\na . getString :: {}\n[\n\tc + \" \" + b\n]\n\n\nMyClass: {}\n[\n\tme.name: \"Sophie\"\n\tme.age: 19\n\t\n\tme\n]\n\ngetString: {MyClass}.{}\n[\n\tname + \" is \" + age + \" years old.\"\n]\n\nperson: MyClass\n\nprint: person.getString\n\n\t> Sophie is 19 years old\n\n___________________________________________________\n\n\nprint \"hello\"\n\nmyFunc 8?\n\tprint \"yes\"\n\t|\n\tprint \"no\"\n\nmyFunc {Int}\n[\n\t\n]\n\n___________________________________________________\n\n\na.b.c: 8\n\n      :\n\t / \\\n    .   8\n   / \\\n  .   c\n / \\\na   b\n\n\n___________________________________________________\n\n\n\ni: 0 | i<100 | i: i+1 @\n(\n\t# do stuff\n)\n\n(i:0; i<100; i:i+1) @\n(\n\t# do stuff\n)\n\n___________________________________________________\n\n\nmyFunc :: {Int}.{Int} -> {Int}:\n(\n\tprint: right\n\tprint: left\n\tprint\n\t\n\tright>6 ?\n\t\tleft.myFunc: right-1\n\t\n\t8\n)\n\nmyFunc :: Int.Int: Int\n(\n\tprint: right\n\tprint: left\n\tprint\n\t\n\tright>6 ?\n\t\tleft.myFunc: right-1\n\t\n\t8\n)\n\n___________________________________________________\n\n\nmyObj: MyObj: 9, 3\n\nmyPtr: &myObj\n\nmyObj = myPtr ? (\n\t# valid\n)\n\nmyObj2 = myPtr.me\n\n___________________________________________________\n\n\nmyObj: MyObj.new: 9, 3\n\nmyPtr: myObj.ptr\n\nmyObj = myPtr ? (\n\t# valid\n)\n\nmyObj2 = myPtr.me\n\n___________________________________________________\n\nmyFunc :: String.Int -> Dub\n[\n\t\n]\n\na: 9.7\nb: int: a\n\n___________________________________________________\n\nvar a\n\na(c: 9, d: 3)\n\n___________________________________________________\n\na: c 9, d 3\n\n___________________________________________________\n\na: happy: MyClass\nb: MyClass\nb: a.diff\n___________________________________________________\n\n"
  },
  {
    "path": "other/readme.md",
    "content": "this directory is for miscellaneous files that don't really go anywhere else.\n"
  },
  {
    "path": "other/user_testing.txt",
    "content": "# what do you think the following code snippits mean?\n\n# 1 _______________________________________________________________________\n\na>b?\n\t~a,\n\t~b\n\n\n# 2 _______________________________________________________________________\n\na: (b: Dub, c: Dub).\n(\n\t# more code here\n)\n\n\n\n# 3 _______________________________________________________________________\n\na:\n(\n\t(b: Dub, c: Dub)=$\n\t\n\t# more code here\n)\n\n\n\n# 4 _______________________________________________________________________\n\na:\n{\n\tb: Int\n\tc: Dub\n\td: {Bool Bool}\n}\n\n\n\n# would you expect the following code to throw an error (assume no other code in the program)?\n# if not, what would you expect it to output?\n\n# 5 _______________________________________________________________________\n\ni: 0, i<6, i++ @\n\tprint: i\n\n\n\n# 6 _______________________________________________________________________\n\na: 3\nb: 2.8\nprint: a+b\n\n\n\n# 7 _______________________________________________________________________\n\na: 3\nb: 2.8\nprint: a+(Int: b)\n\n\n\n# 8 _______________________________________________________________________\n\na: Int\nprint: a\na+=1\nprint: a\n\n\n\n# 9\n# do you prefer ++a, or a++ to increment a variable?\n\na: 5\nprint: a++\n\n\n\n\n"
  },
  {
    "path": "readme.md",
    "content": "# The Pinecone Programming Language\n**_Built from the ground up to be fast, concise and intuitive._**\n\n## NOTE: PINECONE IS NO LONGER BEING ACTIVELY DEVELOPED OR MAINTAINED ## \n\nPinecone is a new programming language. Its goal is to combine the simplicity of a dynamic language with the performance of a compiled one. It is under rapid development, but most of the core features are ready.\n\n__If you want to program in Pinecone now, see the [tutorials](tutorials/index.md) for how to get started.__\n\n__There is also a Pinecone plugin for VIM [here](https://github.com/wsKilljoy/vim-pinecone).__\n\n__For updates, discussion and help, take a look at the Pinecone subreddit: [/r/PineconeLang](https://www.reddit.com/r/PineconeLang/)__\n\n\n## About\nPinecone is a brand new, easy to learn, general purpose, multi-paradigm, high performance programming language created by Sophie Winter. Work on the language began on October 4th, 2016. Pinecone can now be interpreted or transpiled to C++. The language is written from scratch (it includes an integrated lexer, parser and interpreter, etc.).\n\n## Example\nHere is the common demo program FizzBuzz written in Pinecone. It prints the numbers from 1 to 20, but it prints \"Fizz\" if the number is divisible by 3, \"Buzz\" if it is divisable by 5 and \"FizzBuzz\" if it is divisible by both. You can find more samples in the [examples directory](https://github.com/william01110111/Pinecone/tree/master/examples) or the [tutorials](https://github.com/william01110111/Pinecone/tree/master/tutorials).\n\n```\n# FizzBuzz\n\n# call the function defined below\nfizzBuzz: 1, 20\n\n# define the FizzBuzz function\nfizzBuzz :: {start: Int, end: Int}: (\n\n\t# loop i from start to end\n\ti: in.start | i <= in.end | i: i+1 @ (\n\n\t\t# use conditionals to print the right thing\n\n\t\ti % 3 = 0 && i % 5 = 0 ?\n\t\t\tprint: \"FizzBuzz\"\n\t\t|\n\t\ti % 3 = 0 ?\n\t\t\tprint: \"Fizz\"\n\t\t|\n\t\ti % 5 = 0 ?\n\t\t\tprint: \"Buzz\"\n\t\t|\n\t\t\tprint: i\n\t)\n)\n```\n\n## Why?\nThis is probably the most common reaction to hearing about a new language. I realize that there are a __lot__ of programming languages, and that the reason for that is that there are so many assholes like me who keep making them. I do truly think, though, that Pinecone fills a previously empty niche.\n\nPinecone aims to have similar capabilities to modern object oriented compiled languages such as C++, Swift and Rust. It's primary attraction is the simplicity and consistency of it's syntax. Here are some examples of how Pinecone is different from other popular languages:\n\n* Variable creation is implicit, just set a variable and it is created.\n* Variables are statically typed, but type deduction is automatic.\n* Calling a function that takes no arguments is the same syntax as accessing a variable (just writing it's name).\n* Calling a function that takes one argument is the same syntax as setting or creating a variable (`funcOrVar: input`).\n* Calling a function that takes multiple arguments is the same syntax as setting or creating a tuple (`funcOrTuple: input1, input2`).\n* White space is ignored _and_ semicolons are not necessary\n* `:` is used for assignment, which leaves `=` free for comparison, rather than the often confusing `==`.\n* Tuples, structs and classes are all basically the same thing\n* Functions can be sent arguments from the left side, right side or both (`inputLeft.function: inputRight`), which is used for class methods but can also allow you to define functions for any type (even primitive).\n* Program control is done with operators instead of keywords (`?` instead of `if`)\n\n## Compatibility\nPinecone currently requires zero external dependencies (and the only one that will likely be added is LLVM). You will need a C++11 compiler to build it, and the process is easier with GCC and Make. Pinecone has been successfully tested on Linux, MacOS and Windows.\n\n## Current State\nThe features that are currently implemented are as follows:\n\n* Primitive data types `Bool`, `Int` and `Dub`\n* All the operators you would expect (`+`, `*`, `%`, `:`, `=`, `>`, `<=`, `&&`, etc.)\n* Single and multi line comments\n* Flow control (if, if/else, while loop, for loop)\n* Constants\n* Data structs\n* Tuples\n* Int arrays\n* Functions\n* Strings and various String operations\n* User input\n* Running system commands\n* Interpreter for rapid development and simplicity\n* Transpiler to C++ for max performance\n\nThe following features are coming soon:\n\n* Whatev type (equivalent to templates or generics in other languages)\n* Arrays of any type (Whatev support needed)\n* Pass-by-reference\n* Proper classes (pass-by-reference needed)\n* Operator overloading\n\n## Contributing\nI have not yet added enough documentation to the language internals to make it practical for others to contribute to the language itself. If you are interested in adding a specific feature or just helping out, post in the [subreddit](https://www.reddit.com/r/PineconeLang/) or direct message me on [reddit](www.reddit.com/u/william01110111/) or [twitter](https://twitter.com/PineconeLang). Fixes and improvements to the readmes and tutorials are always welcome.\n"
  },
  {
    "path": "repl/readme.md",
    "content": "\n## Repl\n`repl.sh` is a BASH script that creates a Pinecone repl. It supports calling functions and variables, but does not properly handle all symbols (such as `?`) and does not work for multi line expressions.\n\nTo run the repl (after pinecone has been installed):\n\n * Make the `repl.sh` excitable: `chmod +x repl/repl.sh`  \n * Run with `./repl/repl.sh`\n * Optional: Create an alias. Add `alias pinecone=\".../path/to/pinecone/repl/repl.sh\"` to your `.rc` file (`~/.bashrc`, `~/.zshrc`, ect.).\n\nCommands:\n\n * `.clear`: Clears the repl.\n * `.read` : Prints what is in the repl.\n * `.exit` : Exits the repl (same as ^C).\n"
  },
  {
    "path": "repl/repl.sh",
    "content": "#!/bin/bash\necho \"\" > ./repl/tmp.pn;\n\nwhile [ true ]\ndo\n  read -p \"> \" cmd;\n  if [ \"$cmd\" == \".clear\" ]; then\n    echo \"\" > ./repl/tmp.pn;\n    clear;\n    echo \"[cleared]\";\n\n  elif [ \"$cmd\" == \".exit\" ]; then\n    exit 0;\n  elif [ \"$cmd\" == \".read\" ]; then\n    cat ./repl/tmp.pn;\n  else\n    echo $cmd >> ./repl/tmp.pn;\n    echo \" -- \";\n    ./pinecone ./repl/tmp.pn;\n  fi\ndone\n"
  },
  {
    "path": "src/Actions/Action.cpp",
    "content": "#include \"../../h/Action.h\"\n\n#include \"../../h/ErrorHandler.h\"\n\n#include \"../../h/msclStringFuncs.h\"\n\nActionData::ActionData(Type returnTypeIn, Type inLeftTypeIn, Type inRightTypeIn)\n{\n\treturnType=returnTypeIn;\n\tinLeftType=inLeftTypeIn;\n\tinRightType=inRightTypeIn;\n\t\n\tif (!returnType || !inLeftType || !inRightType)\n\t{\n\t\tthrow PineconeError(\"ActionData created with null type\", INTERNAL_ERROR);\n\t}\n}\n\nstring ActionData::toString()\n{\n\treturn description;\n\t\n\t//return returnType->getName() + \" <- \" + inLeftType->getName() + \" \" + text + \" \" + inRightType->getName();\n}\n\nstring ActionData::getTypesString()\n{\n\treturn returnType->getString()+\" <- \"+inLeftType->getString()+\".\"+inRightType->getString();\n}\n\n//LambdaAction::LambdaAction(Type returnTypeIn, function<void*(void*,void*)> lambdaIn, Type inLeftTypeIn, Type inRightTypeIn, string textIn)\n\t\n//void* LambdaAction::execute(void* inLeft, void* inRight)\n\nclass VoidAction: public ActionData\n{\npublic:\n\tVoidAction(): ActionData(Void, Void, Void)\n\t{\n\t\tsetDescription(\"Void Action\");\n\t}\n\t\n\tvoid* execute(void* inLeft, void* inRight)\n\t{\n\t\treturn nullptr;\n\t}\n\t\n\tvoid addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\tif (prog->getExprLevel()>0)\n\t\t\tprog->comment(\"void\");\n\t}\n\t\n\tstring getDescription()\n\t{\n\t\treturn str::putStringInTreeNodeBox(\"void\");\n\t}\n};\n\nclass LambdaAction: public ActionData\n{\npublic:\n\tLambdaAction(Type inLeftTypeIn, Type inRightTypeIn, Type returnTypeIn,\n\t\tfunction<void*(void*,void*)> lambdaIn,\n\t\tfunction<void(Action inLeft, Action inRight, CppProgram* prog)> cppWriterIn,\n\t\tstring textIn)\n\t\t\t: ActionData(returnTypeIn, inLeftTypeIn, inRightTypeIn)\n\t{\n\t\tif (cppWriterIn==nullptr)\n\t\t{\n\t\t\tcppWriter=[=](Action inLeft, Action inRight, CppProgram* prog)\n\t\t\t{\n\t\t\t\tprog->comment(\"lambda action '\"+textIn+\"' has not yet been implemented for C++\");\n\t\t\t};\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcppWriter=cppWriterIn;\n\t\t}\n\t\t\n\t\tif (lambdaIn==nullptr)\n\t\t{\n\t\t\tlambdaIn=[=](void* inLeft, void* inRight)->void*\n\t\t\t{\n\t\t\t\tthrow PineconeError(\"action '\"+textIn+\"' has not yet been implemented for the interpreter\", RUNTIME_ERROR);\n\t\t\t};\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlambda=lambdaIn;\n\t\t}\n\t\t\n\t\tsetDescription(textIn);\n\t}\n\t\n\tvoid* execute(void* inLeft, void* inRight)\n\t{\n\t\treturn lambda(inLeft, inRight);\n\t}\n\t\n\tvoid addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\tcppWriter(inLeft, inRight, prog);\n\t}\n\t\n\tstring getDescription()\n\t{\n\t\treturn str::putStringInTreeNodeBox(description);\n\t}\n\t\nprivate:\n\tfunction<void*(void*,void*)> lambda;\n\tfunction<void(Action inLeft, Action inRight, CppProgram* prog)> cppWriter;\n\tstring cppCode;\n};\n\nAction lambdaAction(Type inLeftTypeIn, Type inRightTypeIn, Type returnTypeIn,\n\tfunction<void*(void*,void*)> lambdaIn,\n\tfunction<void(Action inLeft, Action inRight, CppProgram* prog)> cppWriter,\n\tstring textIn)\n{\n\treturn Action(new LambdaAction(inLeftTypeIn, inRightTypeIn, returnTypeIn, lambdaIn, cppWriter, textIn));\n}\n\nAction createNewVoidAction()\n{\n\treturn Action(new VoidAction());\n}\n"
  },
  {
    "path": "src/Actions/BoolOpAction.cpp",
    "content": "#include \"../../h/Action.h\"\n#include \"../../h/ErrorHandler.h\"\n#include \"../../h/utils/stringDrawing.h\"\n\nclass AndAction: public ActionData\n{\npublic:\n\t\n\tAndAction(Action firstActionIn, Action secondActionIn)\n\t\t:ActionData(Bool, Void, Void)\n\t{\n\t\tfirstAction=firstActionIn;\n\t\tsecondAction=secondActionIn;\n\t\t\n\t\tif (firstAction->getReturnType()!=Bool)\n\t\t{\n\t\t\tthrow PineconeError(\"AndAction created with first action that does not return Bool\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\tif (secondAction->getReturnType()!=Bool)\n\t\t{\n\t\t\tthrow PineconeError(\"AndAction created with second action that does not return Bool\", INTERNAL_ERROR);\n\t\t}\n\t}\n\n\tstring getDescription()\n\t{\n\t\treturn str::makeRootUpBinaryTree(\"&&\", firstAction->getReturnType()->getName(), secondAction->getReturnType()->getName(), firstAction->getDescription(), secondAction->getDescription());\n\t\t//return firstAction->getDescription() + \" && \" + firstAction->getDescription();\n\t}\n\t\n\tvoid* execute(void* inLeft, void* inRight)\n\t{\n\t\tbool* out=(bool*)malloc(sizeof(bool));\n\t\t*out=false;\n\t\tvoid* firstVal=firstAction->execute(nullptr, nullptr);\n\t\t\n\t\tif (*((bool*)firstVal))\n\t\t{\n\t\t\tvoid* secondVal=secondAction->execute(nullptr, nullptr);\n\t\t\t\n\t\t\tif (*((bool*)secondVal))\n\t\t\t{\n\t\t\t\t*out=true;\n\t\t\t}\n\t\t\t\n\t\t\tfree(secondVal);\n\t\t}\n\t\t\n\t\tfree(firstVal);\n\t\t\n\t\treturn out;\n\t}\n\t\n\tvoid addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\tprog->pushExpr();\n\t\t\tfirstAction->addToProg(voidAction, voidAction, prog);\n\t\tprog->popExpr();\n\t\t\n\t\tprog->code(\" && \");\n\t\t\n\t\tprog->pushExpr();\n\t\t\tsecondAction->addToProg(voidAction, voidAction, prog);\n\t\tprog->popExpr();\n\t}\n\t\nprivate:\n\t\n\tAction firstAction;\n\tAction secondAction;\n};\n\nclass OrAction: public ActionData\n{\npublic:\n\t\n\tOrAction(Action firstActionIn, Action secondActionIn)\n\t\t:ActionData(Bool, Void, Void)\n\t{\n\t\tfirstAction=firstActionIn;\n\t\tsecondAction=secondActionIn;\n\t\t\n\t\tif (firstAction->getReturnType()!=Bool)\n\t\t{\n\t\t\tthrow PineconeError(\"OrAction created with first action that does not return Bool\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\tif (secondAction->getReturnType()!=Bool)\n\t\t{\n\t\t\tthrow PineconeError(\"OrAction created with second action that does not return Bool\", INTERNAL_ERROR);\n\t\t}\n\t}\n\n\tstring getDescription()\n\t{\n\t\treturn str::makeRootUpBinaryTree(\"||\", firstAction->getReturnType()->getName(), secondAction->getReturnType()->getName(), firstAction->getDescription(), secondAction->getDescription());\n\t}\n\t\n\tvoid* execute(void* inLeft, void* inRight)\n\t{\n\t\tbool* out=(bool*)malloc(sizeof(bool));\n\t\t*out=true;\n\t\tvoid* firstVal=firstAction->execute(nullptr, nullptr);\n\t\t\n\t\tif (!*((bool*)firstVal))\n\t\t{\n\t\t\tvoid* secondVal=secondAction->execute(nullptr, nullptr);\n\t\t\t\n\t\t\tif (!*((bool*)secondVal))\n\t\t\t{\n\t\t\t\t*out=false;\n\t\t\t}\n\t\t\t\n\t\t\tfree(secondVal);\n\t\t}\n\t\t\n\t\tfree(firstVal);\n\t\t\n\t\treturn out;\n\t}\n\t\n\tvoid addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\tprog->pushExpr();\n\t\t\tfirstAction->addToProg(voidAction, voidAction, prog);\n\t\tprog->popExpr();\n\t\t\n\t\tprog->code(\" || \");\n\t\t\n\t\tprog->pushExpr();\n\t\t\tsecondAction->addToProg(voidAction, voidAction, prog);\n\t\tprog->popExpr();\n\t}\n\t\nprivate:\n\t\n\tAction firstAction;\n\tAction secondAction;\n};\n\nAction andAction(Action firstActionIn, Action secondActionIn)\n{\n\treturn Action(new AndAction(firstActionIn, secondActionIn));\n}\n\nAction orAction(Action firstActionIn, Action secondActionIn)\n{\n\treturn Action(new OrAction(firstActionIn, secondActionIn));\n}\n\n\n"
  },
  {
    "path": "src/Actions/BranchAction.cpp",
    "content": "#include \"../../h/Action.h\"\n#include \"../../h/ErrorHandler.h\"\n#include \"../../h/CppProgram.h\"\n#include \"../../h/utils/stringDrawing.h\"\n\nclass BranchAction: public ActionData\n{\npublic:\n\tBranchAction(Action leftInputIn, Action actionIn, Action rightInputIn)\n\t\t\t:ActionData(actionIn->getReturnType(), Void, Void)\n\t{\n\t\tif (!actionIn)\n\t\t\tthrow PineconeError(string() + \"branch action created sent null action\", INTERNAL_ERROR);\n\t\t\n\t\tif (!leftInputIn)\n\t\t\tthrow PineconeError(string() + \"branch action created sent null leftInput\", INTERNAL_ERROR);\n\t\t\n\t\tif (!rightInputIn)\n\t\t\tthrow PineconeError(string() + \"branch action created sent null rightInput\", INTERNAL_ERROR);\n\t\t\n\t\taction=actionIn;\n\t\tleftInput=leftInputIn;\n\t\trightInput=rightInputIn;\n\t\t\n\t\tif (!leftInput->getInLeftType()->matches(Void) || !leftInput->getInRightType()->matches(Void))\n\t\t{\n\t\t\tthrow PineconeError(leftInput->getDescription() + \" put into branch even though its inputs are not void\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\tif (!rightInput->getInLeftType()->matches(Void) || !rightInput->getInRightType()->matches(Void))\n\t\t{\n\t\t\tthrow PineconeError(rightInput->getDescription() + \" put into branch even though its inputs are not void\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\tif (!leftInput->getReturnType()->matches(action->getInLeftType()))\n\t\t{\n\t\t\tthrow PineconeError(leftInput->getDescription() + \" return type is not the same as the left input of \" + action->getDescription(), INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\tif (!rightInput->getReturnType()->matches(action->getInRightType()))\n\t\t{\n\t\t\tthrow PineconeError(rightInput->getDescription() + \" return type is not the same as the right input of \" + action->getDescription(), INTERNAL_ERROR);\n\t\t}\n\t}\n\n\tstring getDescription()\n\t{\n\t\tif (leftInput && action && rightInput)\n\t\t{\n\t\t\treturn str::makeRootUpBinaryTree(action->getDescription(), leftInput->getReturnType()->getName(), rightInput->getReturnType()->getName(), leftInput->getDescription(), rightInput->getDescription());\n\t\t\t//return getReturnType()->toString() + \" <- [\" + leftInput->getDescription() + \"].[\" + action->getDescription() + \"]:[\" + rightInput->getDescription() + \"]\";\n\t\t\t//return \"(\" + leftInput->getDescription() + \" -> \" + action->getDescription() + \" <- \" + rightInput->getDescription() + \")\";\n\t\t\t//return getReturnType()->getName() + \" <- \" + leftInput->getDescription() + \".\" + action->getDescription() + \":\" + rightInput->getDescription();\n\t\t}\n\t\telse\n\t\t\treturn \"[branch with null element]\";\n\t}\n\n\tvoid* execute(void* inLeft, void* inRight)\n\t{\n\t\tvoid* leftData=leftInput->execute(nullptr, nullptr);\n\t\tvoid* rightData=rightInput->execute(nullptr, nullptr);\n\t\tvoid* outData=action->execute(leftData, rightData);\n\t\tfree(leftData);\n\t\tfree(rightData);\n\t\treturn outData;\n\t}\n\t\n\tvoid addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\tAction leftInTmp = leftInput;\n\t\tAction rightInTmp = rightInput;\n\t\t\n\t\tif (leftInTmp->getReturnType()!=action->getInLeftType())\n\t\t\tleftInTmp=cppTupleCastAction(leftInTmp, action->getInLeftType());\n\t\t\n\t\tif (rightInTmp->getReturnType()!=action->getInRightType())\n\t\t\trightInTmp=cppTupleCastAction(rightInTmp, action->getInRightType());\n\t\t\n\t\taction->addToProg(leftInTmp, rightInTmp, prog);\n\t}\n\t\nprivate:\n\tAction action;\n\tAction leftInput;\n\tAction rightInput;\n};\n\nclass RightBranchAction: public ActionData\n{\npublic:\n\tRightBranchAction(Action actionIn, Action rightInputIn)\n\t\t:ActionData(actionIn->getReturnType(), Void, Void)\n\t{\n\t\tif (!actionIn)\n\t\t\tthrow PineconeError(string() + \"branch action created sent null action\", INTERNAL_ERROR);\n\t\t\t\n\t\tif (!rightInputIn)\n\t\t\tthrow PineconeError(string() + \"branch action created sent null rightInput\", INTERNAL_ERROR);\n\t\t\n\t\taction=actionIn;\n\t\trightInput=rightInputIn;\n\t\t\n\t\tif (!rightInput->getInLeftType()->matches(Void) || !rightInput->getInRightType()->matches(Void))\n\t\t{\n\t\t\tthrow PineconeError(rightInput->getDescription() + \" put into branch even though its inputs are not void\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\tif (!rightInput->getReturnType()->matches(action->getInRightType()))\n\t\t{\n\t\t\tthrow PineconeError(rightInput->getDescription() + \" return type is not the same as the right input of \" + action->getDescription(), INTERNAL_ERROR);\n\t\t}\n\t}\n\t\n\t~RightBranchAction()\n\t{\n\t\t\n\t}\n\n\tstring getDescription()\n\t{\n\t\tif (action && rightInput)\n\t\t{\n\t\t\treturn str::makeRootUpBinaryTree(action->getDescription(), \"\", rightInput->getReturnType()->getName(), \"\", rightInput->getDescription());\n\t\t\t//return getReturnType()->toString() + \" <- [\" + leftInput->getDescription() + \"].[\" + action->getDescription() + \"]:[\" + rightInput->getDescription() + \"]\";\n\t\t\t//return \"(\" + action->getDescription() + \" <- \" + rightInput->getDescription() + \")\";\n\t\t\t//return getReturnType()->getName() + \" <- \" + leftInput->getDescription() + \".\" + action->getDescription() + \":\" + rightInput->getDescription();\n\t\t}\n\t\telse\n\t\t\treturn \"[branch with null element]\";\n\t}\n\t\n\tvoid* execute(void* inLeft, void* inRight)\n\t{\n\t\tvoid* rightData=rightInput->execute(nullptr, nullptr);\n\t\tvoid* outData=action->execute(nullptr, rightData);\n\t\tfree(rightData);\n\t\treturn outData;\n\t}\n\t\n\tvoid addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\tAction rightInTmp = rightInput;\n\t\t\n\t\tif (rightInTmp->getReturnType()!=action->getInRightType())\n\t\t\trightInTmp=cppTupleCastAction(rightInTmp, action->getInRightType());\n\t\t\n\t\taction->addToProg(voidAction, rightInTmp, prog);\n\t}\n\t\nprivate:\n\tAction action=nullptr;\n\tAction rightInput=nullptr;\n};\n\nclass LeftBranchAction: public ActionData\n{\npublic:\n\tLeftBranchAction(Action leftInputIn, Action actionIn)\n\t\t\t:ActionData(actionIn->getReturnType(), Void, Void)\n\t{\n\t\tif (!actionIn)\n\t\t\tthrow PineconeError(string() + \"branch action created sent null action\", INTERNAL_ERROR);\n\t\t\n\t\tif (!leftInputIn)\n\t\t\tthrow PineconeError(string() + \"branch action created sent null leftInput\", INTERNAL_ERROR);\n\t\t\n\t\taction=actionIn;\n\t\tleftInput=leftInputIn;\n\t\t\n\t\tif (!leftInput->getInLeftType()->matches(Void) || !leftInput->getInRightType()->matches(Void))\n\t\t{\n\t\t\tthrow PineconeError(leftInput->getDescription() + \" put into branch even though its inputs are not void\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\tif (!leftInput->getReturnType()->matches(action->getInLeftType()))\n\t\t{\n\t\t\tthrow PineconeError(leftInput->getDescription() + \" return type is not the same as the left input of \" + action->getDescription(), INTERNAL_ERROR);\n\t\t}\n\t}\n\n\tstring getDescription()\n\t{\n\t\tif (leftInput && action)\n\t\t{\n\t\t\treturn str::makeRootUpBinaryTree(action->getDescription(), leftInput->getReturnType()->getName(), \"\", leftInput->getDescription(), \"\");\n\t\t\t//return getReturnType()->toString() + \" <- [\" + leftInput->getDescription() + \"].[\" + action->getDescription() + \"]:[\" + rightInput->getDescription() + \"]\";\n\t\t\t//return \"(\" + leftInput->getDescription() + \" -> \" + action->getDescription() + \")\";\n\t\t\t//return getReturnType()->getName() + \" <- \" + leftInput->getDescription() + \".\" + action->getDescription() + \":\" + rightInput->getDescription();\n\t\t}\n\t\telse\n\t\t\treturn \"[branch with null element]\";\n\t}\n\n\tvoid* execute(void* inLeft, void* inRight)\n\t{\n\t\tvoid* leftData=leftInput->execute(nullptr, nullptr);\n\t\tvoid* outData=action->execute(leftData, nullptr);\n\t\tfree(leftData);\n\t\treturn outData;\n\t}\n\t\n\tvoid addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\tAction leftInTmp = leftInput;\n\t\t\n\t\tif (leftInTmp->getReturnType()!=action->getInLeftType())\n\t\t\tleftInTmp=cppTupleCastAction(leftInTmp, action->getInLeftType());\n\t\t\n\t\taction->addToProg(leftInTmp, voidAction, prog);\n\t}\n\t\nprivate:\n\tAction leftInput;\n\tAction action;\n};\n\nAction branchAction(Action leftInputIn, Action actionIn, Action rightInputIn)\n{\n\t//return Action(new BranchAction(leftInputIn, actionIn, rightInputIn));\n\t\n\t\n\tif (leftInputIn->getReturnType()->isVoid())\n\t{\n\t\tif (rightInputIn->getReturnType()->isVoid())\n\t\t{\n\t\t\treturn actionIn;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn Action(new RightBranchAction(actionIn, rightInputIn));\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (rightInputIn->getReturnType()->isVoid())\n\t\t{\n\t\t\treturn Action(new LeftBranchAction(leftInputIn, actionIn));\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn Action(new BranchAction(leftInputIn, actionIn, rightInputIn));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/Actions/FunctionAction.cpp",
    "content": "\n#include \"../../h/Action.h\"\n#include \"../../h/ErrorHandler.h\"\n#include \"../../h/StackFrame.h\"\n#include \"../../h/AstNode.h\"\n#include \"../../h/utils/stringNumConversion.h\"\n#include \"../../h/utils/stringUtils.h\"\n\n#include <cstring> //for memcpy\nusing std::memcpy;\n\nclass FunctionAction: public ActionData\n{\npublic:\n\t\n\tFunctionAction(Action actionIn, shared_ptr<StackFrame> stackFameIn):\n\t\tActionData(actionIn->getReturnType(), stackFameIn->getLeftInType(), stackFameIn->getRightInType())\n\t{\n\t\tstackFame=stackFameIn;\n\t\taction=actionIn;\n\t\tnode=nullptr;\n\t\t\n\t\tsetDescription(\"function (\"+getInLeftType()->getString()+\".\"+getInRightType()->getString()+\" > \"+getReturnType()->getString()+\")\");\n\t\t\n\t\tif (action->getInLeftType()!=Void || action->getInRightType()!=Void)\n\t\t{\n\t\t\tthrow PineconeError(action->getDescription() + \" put into function even though its inputs are not void\", INTERNAL_ERROR);\n\t\t}\n\t}\n\t\n\tFunctionAction(AstNode nodeIn, Type returnTypeIn, shared_ptr<StackFrame> stackFameIn):\n\t\tActionData(returnTypeIn, stackFameIn->getLeftInType(), stackFameIn->getRightInType())\n\t{\n\t\tstackFame=stackFameIn;\n\t\tnode=move(nodeIn);\n\t\taction=nullptr;\n\t\t\n\t\tsetDescription(\"function (\"+getInLeftType()->getString()+\".\"+getInRightType()->getString()+\" > \"+getReturnType()->getString()+\")\");\n\t}\n\t\n\tvoid resolveAction()\n\t{\n\t\tif (!node || action)\n\t\t{\n\t\t\tthrow PineconeError(\"FunctionAction::resolveAction called when this action is in the wrong state\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\taction=node->getAction();\n\t\t\n\t\tif (!returnType->isVoid() && !returnType->matches(action->getReturnType()))\n\t\t{\n\t\t\t// the objects that are being returned are being destroyed before the function exits\n\t\t\t// also another problem: if a function returns a thing but nothing accepts the output, the destructor is not called\n\t\t\t//throw PineconeError(\"function body returns \"+action->getReturnType()->getString()+\" instead of \"+returnType->getString(), SOURCE_ERROR, node->getToken());\n\t\t\tthrow PineconeError(\"function body returns \"+action->getReturnType()->getString()+\" instead of \"+returnType->getString()+\"\\n\"+action->getDescription(), SOURCE_ERROR, node->getToken());\n\t\t}\n\t\t\n\t\tif (!action->getInLeftType()->isVoid() || !action->getInRightType()->isVoid())\n\t\t{\n\t\t\tthrow PineconeError(action->getDescription() + \" put into function even though its inputs are not void\", INTERNAL_ERROR);\n\t\t}\n\t}\n\t\n\tstring getDescription()\n\t{\n\t\treturn str::putStringInTreeNodeBox(\"call func \"+nameHint);\n\t\t//if (!action)\n\t\t//\tresolveAction();\n\t\t//return \"func: \" + description;//action->getDescription();\n\t}\n\t\n\tbool isFunction() {return true;}\n\t\n\tvoid* execute(void* inLeft, void* inRight)\n\t{\n\t\tif (!action)\n\t\t\tresolveAction();\n\t\t\n\t\tvoid * oldStackPtr=stackPtr;\n\t\t\n\t\tstackPtr=malloc(stackFame->getSize());\n\t\t\n\t\tif (inLeft)\n\t\t\tmemcpy((char*)stackPtr+stackFame->getLeftOffset(), inLeft, getInLeftType()->getSize());\n\t\t\n\t\tif (inRight)\n\t\t\tmemcpy((char*)stackPtr+stackFame->getRightOffset(), inRight, getInRightType()->getSize());\n\t\t\n\t\tvoid* out=action->execute(nullptr, nullptr);\n\t\t\n\t\tfree(stackPtr);\n\t\tstackPtr=oldStackPtr;\n\t\t\n\t\treturn out;\n\t}\n\t\n\tvoid addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\tif (!action)\n\t\t{\n\t\t\tresolveAction();\n\t\t}\n\t\t\n\t\t// construct a unique name that will NEVER collide with another funtion (even in the case of overloaded functions with the same Pinecone name)\n\t\t// note that this name will be used to determine if this function has already been used in C++, so it should generate the same name every time\n\t\tstring name=\"%\";\n\t\t\n\t\tname+=(nameHint.empty() ? \"func\" : nameHint);\n\t\t\n\t\tname+=\"_\"+str::ptrToUniqueStr(&*action);\n\t\t\n\t\t//name+=\"_\"+getInLeftType()->getCompactString()+\"_\"+getInRightType()->getCompactString();\n\t\t\n\t\t/*\n\t\tif (str::hasSuffix(nameHint, \"_CPP\"))\n\t\t\tname=nameHint.substr(0, nameHint.size()-4);\n\t\t*/\n\t\t\n\t\tif (!prog->hasFunc(name))\n\t\t{\n\t\t\tprog->pushFunc(name, getInLeftType(), getInRightType(), getReturnType());\n\t\t\t\tif (getReturnType()->isCreatable() && action->getReturnType()!=getReturnType())\n\t\t\t\t{\n\t\t\t\t\tcppTupleCastAction(action, getReturnType())->addToProg(prog);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\taction->addToProg(prog);\n\t\t\t\t}\n\t\t\t\tprog->endln();\n\t\t\tprog->popFunc();\n\t\t}\n\t\t\n\t\tprog->name(name);\n\t\t\n\t\tprog->pushExpr();\n\t\t\t/*\n\t\t\tbool hasStarted=false;\n\t\t\tif (getInLeftType()->getType()==TypeBase::TUPLE)\n\t\t\t{\n\t\t\t\tfor (auto i: *getInLeftType()->getAllSubTypes())\n\t\t\t\t{\n\t\t\t\t\tif (hasStarted)\n\t\t\t\t\t\tprog->code(\", \");\n\t\t\t\t\thasStarted=true;\n\t\t\t\t\tgetElemFromTupleAction(getInLeftType(), i.name)->addToProg(inLeft, voidAction, prog);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (!getInLeftType()->isCreatable())\n\t\t\t{\n\t\t\t\t// do nothing\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (hasStarted)\n\t\t\t\t\tprog->code(\", \");\n\t\t\t\thasStarted=true;\n\t\t\t\tinLeft->addToProg(prog);\n\t\t\t}\n\t\t\t\n\t\t\tif (getInRightType()->getType()==TypeBase::TUPLE)\n\t\t\t{\n\t\t\t\tfor (auto i: *getInRightType()->getAllSubTypes())\n\t\t\t\t{\n\t\t\t\t\tif (hasStarted)\n\t\t\t\t\t\tprog->code(\", \");\n\t\t\t\t\thasStarted=true;\n\t\t\t\t\tgetElemFromTupleAction(getInRightType(), i.name)->addToProg(inRight, voidAction, prog);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (!getInRightType()->isCreatable())\n\t\t\t{\n\t\t\t\t// do nothing\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (hasStarted)\n\t\t\t\t\tprog->code(\", \");\n\t\t\t\thasStarted=true;\n\t\t\t\tinRight->addToProg(prog);\n\t\t\t}\n\t\t\t//prog->code(\", \");\n\t\t\t//inRight->addToProg(prog);\n\t\t\t*/\n\t\t\t\n\t\t\tif (getInLeftType()->isCreatable())\n\t\t\t{\n\t\t\t\tinLeft->addToProg(prog);\n\t\t\t}\n\t\t\t\n\t\t\tif (getInRightType()->isCreatable())\n\t\t\t{\n\t\t\t\tif (getInLeftType()->isCreatable())\n\t\t\t\t\tprog->code(\", \");\n\t\t\t\t\n\t\t\t\tinRight->addToProg(prog);\n\t\t\t}\n\t\t\t\n\t\tprog->popExpr();\n\t\t\n\t\t//prog->comment(\"function transpiling not yet implemented\");\n\t\t\n\t\t\n\t}\n\t\nprivate:\n\t\n\tshared_ptr<StackFrame> stackFame;\n\tAction action=nullptr;\n\tAstNode node=nullptr;\n};\n\nAction functionAction(Action actionIn, shared_ptr<StackFrame> stackFameIn)\n{\n\treturn Action(new FunctionAction(actionIn, stackFameIn));\n}\n\nAction functionAction(AstNode nodeIn, Type returnTypeIn, shared_ptr<StackFrame> stackFameIn)\n{\n\treturn Action(new FunctionAction(move(nodeIn), returnTypeIn, stackFameIn));\n}\n\n"
  },
  {
    "path": "src/Actions/IfAction.cpp",
    "content": "#include \"../../h/Action.h\"\n#include \"../../h/ErrorHandler.h\"\n\nclass IfAction: public ActionData\n{\npublic:\n\t\n\tIfAction(Action conditionIn, Action ifActionIn)\n\t\t:ActionData(Void, Void, Void)\n\t{\n\t\tcondition=conditionIn;\n\t\tifAction=ifActionIn;\n\t\t\n\t\tif (condition->getReturnType()!=Bool)\n\t\t{\n\t\t\terror.log(\"IfAction created with condition action that does not return Bool\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\tif (condition->getInLeftType()!=Void || condition->getInRightType()!=Void)\n\t\t{\n\t\t\terror.log(\"IfAction created with condition action that takes in something other then Void\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\tif (ifAction->getInLeftType()!=Void || ifAction->getInRightType()!=Void)\n\t\t{\n\t\t\terror.log(\"IfAction created with action that takes in something other then Void\", INTERNAL_ERROR);\n\t\t}\n\t}\n\n\tstring getDescription()\n\t{\n\t\treturn str::makeRootUpBinaryTree(\"?\", condition->getReturnType()->getName(), \"\", condition->getDescription(), ifAction->getDescription());\n\t\t//return \"if \" + condition->getDescription() + \" then \" + ifAction->getDescription();\n\t}\n\n\tvoid* execute(void* inLeft, void* inRight)\n\t{\n\t\tvoid* conditionOut=condition->execute(nullptr, nullptr);\n\t\tif (*((bool*)conditionOut))\n\t\t{\n\t\t\tfree(ifAction->execute(nullptr, nullptr));\n\t\t}\n\t\tfree(conditionOut);\n\t\treturn nullptr;\n\t}\n\t\n\tvoid addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\tprog->code(\"if \");\n\t\tprog->pushExpr();\n\t\tcondition->addToProg(voidAction, voidAction, prog);\n\t\tprog->popExpr();\n\t\tprog->pushBlock();\n\t\tifAction->addToProg(voidAction, voidAction, prog);\n\t\tprog->endln();\n\t\tprog->popBlock();\n\t}\n\t\nprivate:\n\t\n\tAction condition;\n\tAction ifAction;\n};\n\nclass IfElseAction: public ActionData\n{\npublic:\n\t\n\tIfElseAction(Action conditionIn, Action ifActionIn, Action elseActionIn)\n\t\t:ActionData([&](){return ifActionIn->getReturnType()->matches(elseActionIn->getReturnType())?ifActionIn->getReturnType():Void;}(), Void, Void)\n\t{\n\t\treturnVal=getReturnType()!=Void;\n\t\tcondition=conditionIn;\n\t\tifAction=ifActionIn;\n\t\telseAction=elseActionIn;\n\t\t\n\t\tif (condition->getReturnType()!=Bool)\n\t\t{\n\t\t\terror.log(\"IfElseAction created with condition action that does not return Bool\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\tif (condition->getInLeftType()!=Void || condition->getInRightType()!=Void)\n\t\t{\n\t\t\terror.log(\"IfElseAction created with conditiofn action that takes in something other then Void\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\tif (ifAction->getInLeftType()!=Void || ifAction->getInRightType()!=Void)\n\t\t{\n\t\t\terror.log(\"IfElseAction created with action that takes in something other then Void\", INTERNAL_ERROR);\n\t\t}\n\t}\n\n\tstring getDescription()\n\t{\n\t\tstring branch=str::makeRootUpBinaryTree(\"╭┴╮\\n│ │\", \"fls\", \"tru\", elseAction->getDescription(), ifAction->getDescription());\n\t\treturn str::makeRootUpBinaryTree(\"?\", condition->getReturnType()->getName(), \"\", condition->getDescription(), branch);\n\t\t//return \"if \" + condition->getDescription() + \" then \" + ifAction->getDescription();\n\t}\n\n\t/*\n\tstring getCSource(string inLeft, string inRight)\n\t{\n\t\treturn \"if (\" + condition->getCSource() + \")\\n{\\n\" + ifAction->getCSource() + \"\\n} else {\\n\" + elseAction->getCSource() + \"\\n}\";\n\t}\n\t*/\n\t\n\tvoid* execute(void* inLeft, void* inRight)\n\t{\n\t\tvoid* out;\n\t\tvoid* conditionOut=condition->execute(nullptr, nullptr);\n\t\tif (*((bool*)conditionOut))\n\t\t{\n\t\t\tout=ifAction->execute(nullptr, nullptr);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tout=elseAction->execute(nullptr, nullptr);\n\t\t}\n\t\tfree(conditionOut);\n\t\tif (returnVal)\n\t\t{\n\t\t\treturn out;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfree(out);\n\t\t\treturn nullptr;\n\t\t}\n\t}\n\t\n\tvoid addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\tif (returnVal && prog->getExprLevel()>0)\n\t\t{\n\t\t\tprog->pushExpr();\n\t\t\t\tcondition->addToProg(voidAction, voidAction, prog);\n\t\t\tprog->popExpr();\n\t\t\tprog->code(\" ? \");\n\t\t\tprog->pushExpr();\n\t\t\t\tifAction->addToProg(voidAction, voidAction, prog);\n\t\t\tprog->popExpr();\n\t\t\tprog->code(\" : \");\n\t\t\tprog->pushExpr();\n\t\t\t\telseAction->addToProg(voidAction, voidAction, prog);\n\t\t\tprog->popExpr();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tprog->code(\"if \");\n\t\t\tprog->pushExpr();\n\t\t\t\tcondition->addToProg(voidAction, voidAction, prog);\n\t\t\tprog->popExpr();\n\t\t\tprog->pushBlock();\n\t\t\t\tifAction->addToProg(voidAction, voidAction, prog);\n\t\t\t\tprog->endln();\n\t\t\tprog->popBlock();\n\t\t\tprog->code(\"else\");\n\t\t\tprog->pushBlock();\n\t\t\t\telseAction->addToProg(voidAction, voidAction, prog);\n\t\t\t\tprog->endln();\n\t\t\tprog->popBlock();\n\t\t}\n\t}\n\t\nprivate:\n\t\n\tAction condition;\n\tAction ifAction;\n\tAction elseAction;\n\tbool returnVal=false;\n};\n\nAction ifAction(Action conditionIn, Action ifActionIn)\n{\n\treturn Action(new IfAction(conditionIn, ifActionIn));\n}\n\nAction ifElseAction(Action conditionIn, Action ifActionIn, Action elseAction)\n{\n\treturn Action(new IfElseAction(conditionIn, ifActionIn, elseAction));\n}\n\n\n"
  },
  {
    "path": "src/Actions/ListAction.cpp",
    "content": "#include \"../../h/Action.h\"\n#include \"../../h/ErrorHandler.h\"\n\nclass ListAction: public ActionData\n{\npublic:\n\t\n\tListAction(const vector<Action>& actionsIn, const vector<Action>& destroyersIn):\n\t\tActionData\n\t\t(\n\t\t\t(actionsIn.size()>0?actionsIn.back()->getReturnType():Void),\n\t\t\tVoid, Void\n\t\t)\n\t{\n\t\tactions=actionsIn;\n\t\tdestroyers=destroyersIn;\n\t\t\n\t\tfor (auto i=actions.begin(); i!=actions.end(); ++i)\n\t\t{\n\t\t\tif (!(*i)->getInLeftType()->matches(Void) || !(*i)->getInRightType()->matches(Void))\n\t\t\t{\n\t\t\t\terror.log((*i)->getDescription() + \" put into action list even though its inputs are not void\", INTERNAL_ERROR);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t~ListAction() \n\t{\n\t\t\n\t}\n\n\tstring getDescription()\n\t{\n\t\tvector<string> data;\n\t\t\n\t\tfor (auto i=actions.begin(); i!=actions.end(); ++i)\n\t\t{\n\t\t\tif (*i)\n\t\t\t\tdata.push_back((*i)->getDescription());\n\t\t\telse\n\t\t\t\tdata.push_back(str::putStringInTreeNodeBox(\"[null action]\"));\n\t\t}\n\t\t\n\t\treturn str::makeList(data);\n\t\t/*\n\t\tstring out;\n\t\tout+=\"\\n{\";\n\t\t\n\t\tfor (auto i=actions.begin(); i!=actions.end(); ++i)\n\t\t{\n\t\t\tout+=\"\\n\\t\";\n\t\t\t\n\t\t\tstring str;\n\t\t\t\n\t\t\tif (*i)\n\t\t\t\tstr=(*i)->getDescription();\n\t\t\telse\n\t\t\t\tstr=\"[null action]\";\n\t\t\t\n\t\t\tfor (unsigned j=0; j<str.size(); ++j)\n\t\t\t{\n\t\t\t\tout+=str[j];\n\t\t\t\t\n\t\t\t\tif (str[j]=='\\n')\n\t\t\t\t\tout+='\\t';\n\t\t\t}\n\t\t\t\n\t\t\tout+=\"\\n\";\n\t\t}\n\t\t\n\t\tout+=\"}\\n\";\n\t\t\n\t\treturn out;\n\t\t*/\n\t}\n\t\n\tvoid* execute(void* inLeft, void* inRight)\n\t{\n\t\tauto i=actions.begin();\n\t\t\n\t\tfor (; i!=std::prev(actions.end()); ++i)\n\t\t{\n\t\t\tfree((*i)->execute(nullptr, nullptr));\n\t\t}\n\t\t\n\t\tvoid* returnVal=(*i)->execute(nullptr, nullptr);\n\t\t\n\t\tfor (auto j: destroyers)\n\t\t{\n\t\t\tfree(j->execute(nullptr, nullptr));\n\t\t}\n\t\t\n\t\treturn returnVal;\n\t}\n\t\n\tvoid addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\taddToProg(prog, getReturnType());\n\t}\n\t\n\tvoid addToProg(CppProgram* prog, Type returnType)\n\t{\n\t\tbool shouldReturn=(prog->getBlockLevel()==0 && prog->getIfReturnsVal()) && !prog->isMain();\n\t\t\n\t\tprog->pushBlock();\n\t\t\n\t\tfor (auto i: actions)\n\t\t{\n\t\t\tif (shouldReturn && i==actions.back())\n\t\t\t{\n\t\t\t\tprog->declareVar(\"-out\", returnType);\n\t\t\t\tprog->name(\"-out\");\n\t\t\t\tprog->code(\" = \");\n\t\t\t\tif (i->getReturnType()!=returnType)\n\t\t\t\t{\n\t\t\t\t\tcppTupleCastAction(i, returnType)->addToProg(prog);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ti->addToProg(prog);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ti->addToProg(prog);\n\t\t\t}\n\t\t\tprog->endln();\n\t\t}\n\t\t\n\t\tfor (auto i: destroyers)\n\t\t{\n\t\t\ti->addToProg(prog);\n\t\t\tprog->endln();\n\t\t}\n\t\t\n\t\tif (shouldReturn)\n\t\t{\n\t\t\tprog->code(\"return \");\n\t\t\tprog->name(\"-out\");\n\t\t\tprog->endln();\n\t\t}\n\t\t\n\t\tprog->popBlock();\n\t}\n\t\n\t/*\n\tstring getCSource(string inLeft, string inRight)\n\t{\n\t\tstring out;\n\t\t\n\t\tfor (auto i: actions)\n\t\t{\n\t\t\tout+=i->getCSource()+\";\\n\";\n\t\t}\n\t\t\n\t\treturn out;\n\t}\n\t*/\n\t\n\t\n\t\nprivate:\n\tvector<Action> actions;\n\tvector<Action> destroyers;\n};\n\nvoid addListToProgWithCppCasting(ListAction* list, Type returnType, CppProgram* prog)\n{\n\tlist->addToProg(prog, returnType);\n}\n\nAction listAction(const vector<Action>& actionsIn, const vector<Action>& destroyersIn)\n{\n\tif (actionsIn.size()==0 && destroyersIn.size()==0)\n\t{\n\t\treturn voidAction;\n\t}\n\telse if (actionsIn.size()==1 && destroyersIn.size()==0)\n\t{\n\t\treturn actionsIn[0];\n\t}\n\telse\n\t{\n\t\treturn Action(new ListAction(actionsIn, destroyersIn));\n\t}\n}\n\n"
  },
  {
    "path": "src/Actions/LoopAction.cpp",
    "content": "#include \"../../h/Action.h\"\n#include \"../../h/ErrorHandler.h\"\n\nclass LoopAction: public ActionData\n{\npublic:\n\t\n\tLoopAction(Action conditionIn, Action endActionIn, Action loopActionIn)\n\t\t:ActionData(Void, Void, Void)\n\t{\n\t\tcondition=conditionIn;\n\t\tloopAction=loopActionIn;\n\t\tendAction=endActionIn;\n\t\t\n\t\tif (condition->getReturnType()!=Bool)\n\t\t{\n\t\t\terror.log(\"LoopAction created with condition action that does not return Bool\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\tif (condition->getInLeftType()!=Void || condition->getInRightType()!=Void)\n\t\t{\n\t\t\terror.log(\"LoopAction created with condition action that takes in something other then Void\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\tif (loopAction->getInLeftType()!=Void || loopAction->getInRightType()!=Void)\n\t\t{\n\t\t\terror.log(\"LoopAction created with action that takes in something other then Void\", INTERNAL_ERROR);\n\t\t}\n\t}\n\n\tstring getDescription()\n\t{\n\t\tstring body=loopAction->getDescription();\n\t\tif (endAction!=voidAction)\n\t\t{\n\t\t\tvector<string> data={body, endAction->getDescription()};\n\t\t\tbody=str::makeList(data);\n\t\t}\n\t\treturn str::makeRootUpBinaryTree(\"@\", condition->getReturnType()->getName(), \"\", condition->getDescription(), body);\n\t\t//return \"while \" + condition->getDescription() + \" do \" + loopAction->getDescription();\n\t}\n\t\n\tvoid* execute(void* inLeft, void* inRight)\n\t{\n\t\tvoid* conditionOut;\n\t\t\n\t\twhile (true)\n\t\t{\n\t\t\tconditionOut=condition->execute(nullptr, nullptr);\n\t\t\tif (!(*((bool*)conditionOut)))\n\t\t\t\tbreak;\n\t\t\tfree(conditionOut);\n\t\t\tfree(loopAction->execute(nullptr, nullptr));\n\t\t\tfree(endAction->execute(nullptr, nullptr));\n\t\t}\n\t\t\n\t\tfree(conditionOut);\n\t\t\n\t\treturn nullptr;\n\t}\n\t\n\t/*\n\tstring getCSource(string inLeft, string inRight)\n\t{\n\t\tstring out;\n\t\t\n\t\tout+=\"while (\";\n\t\tout+=condition->getCSource();\n\t\tout+=\")\\n{\";\n\t\tout+=loopAction->getCSource();\n\t\tout+=endAction->getCSource();\n\t\tout+=\"\\n}\";\n\t\t\n\t\treturn out;\n\t}\n\t*/\n\t\n\tvoid addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\tprog->code(\"while \");\n\t\t\n\t\tprog->pushExpr();\n\t\t\tcondition->addToProg(prog);\n\t\tprog->popExpr();\n\t\t\n\t\tprog->pushBlock();\n\t\t\tloopAction->addToProg(prog);\n\t\t\tprog->endln();\n\t\t\tif (endAction!=voidAction)\n\t\t\t{\n\t\t\t\tendAction->addToProg(prog);\n\t\t\t\tprog->endln();\n\t\t\t}\n\t\tprog->popBlock();\n\t}\n\t\nprivate:\n\t\n\tAction condition;\n\tAction loopAction;\n\tAction endAction;\n};\n\nAction loopAction(Action conditionIn, Action loopActionIn)\n{\n\treturn Action(new LoopAction(conditionIn, voidAction, loopActionIn));\n}\n\nAction loopAction(Action conditionIn, Action endActionIn, Action loopActionIn)\n{\n\treturn Action(new LoopAction(conditionIn, endActionIn, loopActionIn));\n}\n\n\n"
  },
  {
    "path": "src/Actions/MakeTupleAction.cpp",
    "content": "#include \"../../h/Action.h\"\n#include \"../../h/ErrorHandler.h\"\n\n#include <vector>\n#include <typeinfo>\n\nusing std::vector;\n\nclass GetElemFromTupleAction;\nclass CppTupleCastAction;\n\nclass ListAction;\nvoid addListToProgWithCppCasting(ListAction* list, Type returnType, CppProgram* prog);\n\nclass MakeTupleAction: public ActionData\n{\npublic:\n\t\n\tMakeTupleAction(const vector<Action>& sourceActionsIn):\n\t\tActionData(\n\t\t\t[&]() -> Type\n\t\t\t{\n\t\t\t\tTupleTypeMaker tuple;\n\t\t\t\t\n\t\t\t\tfor (auto i=sourceActionsIn.begin(); i!=sourceActionsIn.end(); ++i)\n\t\t\t\t{\n\t\t\t\t\ttuple.add((*i)->getReturnType());\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn tuple.get(true);\n\t\t\t}(),\n\t\t\t\n\t\t\tVoid, Void\n\t\t)\n\t{\n\t\tif (sourceActionsIn.size()<=0)\n\t\t{\n\t\t\terror.log(\"MakeTupleAction created with empty list\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\tsourceActions=sourceActionsIn;\n\t\t\n\t\tfor (auto i=sourceActions.begin(); i!=sourceActions.end(); ++i)\n\t\t{\n\t\t\tif (!(*i)->getInLeftType()->matches(Void) || !(*i)->getInRightType()->matches(Void))\n\t\t\t{\n\t\t\t\terror.log((*i)->getDescription() + \" put into tuple creation even though its inputs are not void\", INTERNAL_ERROR);\n\t\t\t}\n\t\t\t\n\t\t\tif ((*i)->getReturnType()->matches(Void))\n\t\t\t{\n\t\t\t\terror.log((*i)->getDescription() + \" put into tuple creation even though its output is void\", INTERNAL_ERROR);\n\t\t\t}\n\t\t}\n\t}\n\n\tstring getDescription()\n\t{\n\t\treturn str::putStringInTreeNodeBox(\"make tuple of type \"+getReturnType()->getName());\n\t\t\n\t\t//return \"[tuple of type \" + getReturnType()->getString() + \"]\";\n\t\t\n\t\t/*string out;\n\t\tout+=\"\\n{\";\n\t\t\n\t\tfor (auto i=sourceActions.begin(); i!=sourceActions.end(); ++i)\n\t\t{\n\t\t\tout+=\"\\n\\t\";\n\t\t\t\n\t\t\tstring str;\n\t\t\t\n\t\t\tif (*i)\n\t\t\t\tstr=(*i)->getDescription();\n\t\t\telse\n\t\t\t\tstr=\"[null action]\";\n\t\t\t\n\t\t\tfor (unsigned j=0; j<str.size(); ++j)\n\t\t\t{\n\t\t\t\tout+=str[j];\n\t\t\t\t\n\t\t\t\tif (str[j]=='\\n')\n\t\t\t\t\tout+='\\t';\n\t\t\t}\n\t\t\t\n\t\t\tout+=\"\\n\";\n\t\t}\n\t\t\n\t\tout+=\"}\\n\";\n\t\t\n\t\treturn out;*/\n\t}\n\t\n\tvoid* execute(void* inLeft, void* inRight)\n\t{\n\t\tvoid* out=malloc(getReturnType()->getSize());\n\t\tsize_t offset=0;\n\t\t\n\t\tfor (auto i=sourceActions.begin(); i!=sourceActions.end(); ++i)\n\t\t{\n\t\t\tvoid* val=(*i)->execute(nullptr, nullptr);\n\t\t\tmemcpy((char*)out+offset, val, (*i)->getReturnType()->getSize());\n\t\t\tfree(val);\n\t\t\toffset+=(*i)->getReturnType()->getSize();\n\t\t}\n\t\t\n\t\treturn out;\n\t}\n\t\n\tvoid addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\tif (sourceActions.size()==1)\n\t\t{\n\t\t\tsourceActions[0]->addToProg(prog);\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tprog->code(prog->getTypeCode(getReturnType()));\n\t\tprog->pushExpr();\n\t\tbool start=true;\n\t\tfor (auto i: sourceActions)\n\t\t{\n\t\t\tif (!start) prog->code(\", \");\n\t\t\tstart=false;\n\t\t\t\n\t\t\ti->addToProg(prog);\n\t\t}\n\t\tprog->popExpr();\n\t}\n\t\n\t\nprivate:\n\t\n\tvector<Action> sourceActions;\n\t\n\tfriend GetElemFromTupleAction;\n\tfriend CppTupleCastAction;\n};\n\nclass CppTupleCastAction: public ActionData\n{\npublic:\n\t\n\tCppTupleCastAction(Action actionIn, Type returnType):\n\t\tActionData(returnType, Void, Void)\n\t{\n\t\tif ((actionIn->getReturnType()->getType()!=TypeBase::TUPLE && getReturnType()->getType()!=TypeBase::TUPLE) || !actionIn->getReturnType()->matches(getReturnType()))\n\t\t{\n\t\t\tthrow PineconeError(\"CppCastAction was only designed to cast matching tuples, which is not how it is being used\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\taction=actionIn;\n\t}\n\t\n\tstring getDescription()\n\t{\n\t\treturn \"C++ cast\";\n\t}\n\t\n\tvoid* execute(void* inLeft, void* inRight)\n\t{\n\t\tthrow PineconeError(\"CppCastAction was executed in the interpreter, which shouldn't happen\", INTERNAL_ERROR);\n\t}\n\t\n\tvoid addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\tif (getReturnType()->getAllSubTypes()->size()==1)\n\t\t{\n\t\t\taction->addToProg(prog);\n\t\t}\n\t\telse if (typeid(*action)==typeid(MakeTupleAction))\n\t\t{\n\t\t\tMakeTupleAction * realAction=(MakeTupleAction*)&*action;\n\t\t\t\n\t\t\tprog->code(prog->getTypeCode(getReturnType()));\n\t\t\tprog->pushExpr();\n\t\t\t\tfor (auto i: realAction->sourceActions)\n\t\t\t\t{\n\t\t\t\t\ti->addToProg(prog);\n\t\t\t\t\tif (i!=realAction->sourceActions.back())\n\t\t\t\t\t\tprog->code(\", \");\n\t\t\t\t}\n\t\t\tprog->popExpr();\n\t\t}\n\t\telse if (typeid(*action)==typeid(*listAction({voidAction, voidAction}, {})))\n\t\t{\n\t\t\taddListToProgWithCppCasting((ListAction*)&*action, getReturnType(), prog);\n\t\t}\n\t\telse if (getReturnType()->getType()!=TypeBase::TUPLE)\n\t\t{\n\t\t\taction->addToProg(prog);\n\t\t\tprog->code(\".\");\n\t\t\tprog->code(action->getReturnType()->getAllSubTypes()[0][0].name);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstring funcName=action->getReturnType()->getCompactString()+\"=>\"+getReturnType()->getCompactString();\n\t\t\t\n\t\t\tif (!prog->hasFunc(funcName))\n\t\t\t{\n\t\t\t\tType argType=makeTuple({{\"in\", action->getReturnType()}}, true);\n\t\t\t\t\n\t\t\t\tprog->pushFunc(funcName, \"\", Void, argType, getReturnType());\n\t\t\t\t\tprog->declareVar(\"-out\", getReturnType());\n\t\t\t\t\t\n\t\t\t\t\tauto outTypes=*getReturnType()->getAllSubTypes();\n\t\t\t\t\t\n\t\t\t\t\tif (action->getReturnType()->getType()==TypeBase::TUPLE)\n\t\t\t\t\t{\n\t\t\t\t\t\tauto inTypes=*action->getReturnType()->getAllSubTypes();\n\t\t\t\t\t\t\n\t\t\t\t\t\tfor (int i=0; i<int(inTypes.size()); i++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//if (inTypes[i].type==outTypes[i].type)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tprog->name(\"-out\");\n\t\t\t\t\t\t\t\tprog->code(\".\");\n\t\t\t\t\t\t\t\tprog->code(outTypes[i].name);\n\t\t\t\t\t\t\t\tprog->code(\" = \");\n\t\t\t\t\t\t\t\tprog->name(\"in\");\n\t\t\t\t\t\t\t\tprog->code(\".\");\n\t\t\t\t\t\t\t\tprog->code(inTypes[i].name);\n\t\t\t\t\t\t\t\tprog->endln();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tprog->name(\"-out\");\n\t\t\t\t\t\tprog->code(\".\");\n\t\t\t\t\t\tprog->code(outTypes[0].name);\n\t\t\t\t\t\tprog->code(\" = \");\n\t\t\t\t\t\tprog->name(\"in\");\n\t\t\t\t\t\tprog->endln();\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tprog->code(\"return \");\n\t\t\t\t\tprog->name(\"-out\");\n\t\t\t\t\tprog->endln();\n\t\t\t\t\t\n\t\t\t\tprog->popFunc();\n\t\t\t}\n\t\t\t\n\t\t\tprog->name(funcName);\n\t\t\tprog->pushExpr();\n\t\t\t\taction->addToProg(prog);\n\t\t\tprog->popExpr();\n\t\t}\n\t}\n\t\nprivate:\n\t\n\tAction action;\n\t\n\tfriend GetElemFromTupleAction;\n};\n\nclass GetElemFromTupleAction: public ActionData\n{\npublic:\n\t\n\tGetElemFromTupleAction(Type typeInIn, string nameIn):\n\t\tActionData(typeInIn->getSubType(nameIn).type, typeInIn, Void)\n\t{\n\t\ttypeIn=typeInIn;\n\t\ttypeOut=typeInIn->getSubType(nameIn).type;\n\t\t// if no type was found, the ActionData constructor would have already thrown an error\n\t\tname=nameIn;\n\t\tsize=typeOut->getSize();\n\t\toffset=typeIn->getSubType(name).offset;\n\t}\n\t\n\tstring getDescription()\n\t{\n\t\treturn str::putStringInTreeNodeBox(name);\n\t\t//return \"get element from tuple\";\n\t}\n\t\n\tvoid* execute(void* inLeft, void* inRight)\n\t{\n\t\tvoid* out=malloc(size);\n\t\tmemcpy(out, (char*)inLeft+offset, size);\n\t\treturn out;\n\t}\n\t\n\tvoid addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\tif (typeIn->getAllSubTypes()->size()==1)\n\t\t{\n\t\t\tinLeft->addToProg(prog);\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tMakeTupleAction * makeTupleAction=nullptr;\n\t\t\n\t\tif (typeid(*inLeft)==typeid(MakeTupleAction))\n\t\t{\n\t\t\tmakeTupleAction=(MakeTupleAction *)&*inLeft;\n\t\t}\n\t\t\n\t\telse if (typeid(*inLeft)==typeid(CppTupleCastAction))\n\t\t{\n\t\t\tAction castAction=((CppTupleCastAction *)&*inLeft)->action;\n\t\t\t\n\t\t\tif (typeid(*castAction)==typeid(MakeTupleAction))\n\t\t\t{\n\t\t\t\tmakeTupleAction=(MakeTupleAction *)&*castAction;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (makeTupleAction)\n\t\t{\n\t\t\tauto types=*inLeft->getReturnType()->getAllSubTypes();\n\t\t\t\n\t\t\tfor (int i=0; i<int(types.size()); i++)\n\t\t\t{\n\t\t\t\tif (types[i].name==name)\n\t\t\t\t{\n\t\t\t\t\tmakeTupleAction->sourceActions[i]->addToProg(prog);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/*\n\t\t\tif (inLeft->nameHint==\"in\" || inLeft->nameHint==\"me\")\n\t\t\t{\n\t\t\t\tprog->code(name);\n\t\t\t}\n\t\t\telse\n\t\t\t*/\n\t\t\t{\n\t\t\t\tinLeft->addToProg(prog);\n\t\t\t\tprog->code(\".\"+name);\n\t\t\t}\n\t\t}\n\t}\n\t\nprivate:\n\tType typeIn;\n\tType typeOut;\n\tint offset;\n\tsize_t size;\n\tstring name;\n};\n\nAction makeTupleAction(const std::vector<Action>& sourceActionsIn)\n{\n\treturn Action(new MakeTupleAction(sourceActionsIn));\n}\n\nAction getElemFromTupleAction(Type source, string name)\n{\n\tif (!source->getSubType(name).type)\n\t\tthrow PineconeError(\"could not find '\"+name+\"' in \"+source->getString(), SOURCE_ERROR);\n\t\n\tAction out=Action(new GetElemFromTupleAction(source, name));\n\t\n\treturn out;\n}\n\nAction cppTupleCastAction(Action actionIn, Type returnType)\n{\n\treturn Action(new CppTupleCastAction(actionIn, returnType));\n}\n\n"
  },
  {
    "path": "src/Actions/TypeAction.cpp",
    "content": "#include \"../../h/Action.h\"\n#include \"../../h/ErrorHandler.h\"\n\nclass TypeGetAction: public ActionData\n{\npublic:\n\t\n\tTypeGetAction(Type typeIn):\n\t\tActionData(typeIn->getMeta(), Void, Void)\n\t{\n\t\tsetDescription(typeIn->getString()+\" (type)\");\n\t}\n\t\n\tstring getCSource(string inLeft, string inRight)\n\t{\n\t\treturn \"/* C source for TypeGetAction not yet implemented */\";\n\t}\n\t\n\tvoid* execute(void* inLeft, void* inRight)\n\t{\n\t\terror.log(\"TypeGetAction::execute called, which shouldn't happen\", RUNTIME_ERROR);\n\t\t\n\t\treturn nullptr;\n\t}\n\t\n\tstring getDescription()\n\t{\n\t\treturn str::putStringInTreeNodeBox(\"{\"+getReturnType()->getName()+\"}\");\n\t}\n\t\nprivate:\n};\n\nAction typeGetAction(Type typeIn)\n{\n\treturn Action(new TypeGetAction(typeIn));\n}\n"
  },
  {
    "path": "src/Actions/VarAction.cpp",
    "content": "#include \"../../h/Action.h\"\n#include \"../../h/ErrorHandler.h\"\n#include \"../../h/StackFrame.h\"\n#include \"../../h/CppProgram.h\"\n#include \"../../h/utils/stringNumConversion.h\"\n#include \"../../h/Namespace.h\"\n#include \"../../h/utils/stringDrawing.h\"\n\nclass VarGetAction: public ActionData\n{\npublic:\n\t\n\tVarGetAction(size_t in, void ** stackPtrPtrIn, Type typeIn, string idIn):\n\t\tActionData(typeIn, Void, Void)\n\t{\n\t\toffset=in;\n\t\tstackPtrPtr=stackPtrPtrIn;\n\t\tnameHint=idIn;\n\t\t\n\t\tsetDescription(\"get \" + typeIn->getString() + \" '\" + idIn + \"'\");\n\t\t\n\t}\n\t\n\tvoid* execute(void* inLeft, void* inRight)\n\t{\n\t\tif (!(*stackPtrPtr))\n\t\t{\n\t\t\tthrow PineconeError(\"something fucked up big time. VarGetAction::execute called while stack pointer is still null\", RUNTIME_ERROR);\n\t\t}\n\t\t\n\t\tvoid* out=malloc(returnType->getSize());\n\t\tmemcpy(out, (char*)(*stackPtrPtr)+offset, returnType->getSize());\n\t\treturn out;\n\t}\n\t\n\tvoid addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\t/*\n\t\tif ((nameHint==\"me\" || nameHint==\"in\") && getReturnType()->getType()==TypeBase::TUPLE)\n\t\t{\n\t\t\tprog->code(prog->getTypeCode(getReturnType()));\n\t\t\tprog->pushExpr();\n\t\t\t\tbool isFirst=true;\n\t\t\t\tfor (auto i: *getReturnType()->getAllSubTypes())\n\t\t\t\t{\n\t\t\t\t\tif (!isFirst)\n\t\t\t\t\t\tprog->code(\", \");\n\t\t\t\t\tisFirst=false;\n\t\t\t\t\tprog->name(i.name);\n\t\t\t\t}\n\t\t\tprog->popExpr();\n\t\t}\n\t\telse\n\t\t*/\n\t\t{\n\t\t\tprog->declareVar(nameHint, getReturnType());\n\t\t\tprog->name(nameHint);\n\t\t}\n\t}\n\t\n\tstring getDescription()\n\t{\n\t\treturn str::putStringInTreeNodeBox(\"get \"+nameHint);\n\t}\n\t\nprivate:\n\t\n\tvoid ** stackPtrPtr;\n\tsize_t offset;\n};\n\nclass VarSetAction: public ActionData\n{\npublic:\n\t\n\tVarSetAction(size_t in, void ** stackPtrPtrIn, Type typeIn, string idIn):\n\t\tActionData(Void, Void, typeIn)\n\t{\n\t\toffset=in;\n\t\tstackPtrPtr=stackPtrPtrIn;\n\t\tnameHint=idIn;\n\t\t\n\t\tsetDescription(\"set \" + typeIn->getString() + \" '\" + idIn + \"'\");\n\t}\n\t\n\tvoid* execute(void* left, void* right)\n\t{\n\t\tif (!(*stackPtrPtr))\n\t\t{\n\t\t\tthrow PineconeError(\"something fucked up big time. VarSetAction::execute called while stack pointer is still null\", RUNTIME_ERROR);\n\t\t}\n\t\t\n\t\t//copy data on to the stack location of the var\n\t\tmemcpy((char*)(*stackPtrPtr)+offset, right, inRightType->getSize());\n\t\t\n\t\t//return a new copy of the data\n\t\tvoid* out=malloc(returnType->getSize());\n\t\tmemcpy(out, (char*)(*stackPtrPtr)+offset, inRightType->getSize());\n\t\t//return out;\n\t\treturn nullptr;\n\t}\n\t\n\tvoid addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\t/*\n\t\tif ((nameHint==\"me\" || nameHint==\"in\") && getReturnType()->getType()==TypeBase::TUPLE)\n\t\t{\n\t\t\tif (prog->getExprLevel()>0)\n\t\t\t{\n\t\t\t\tthrow PineconeError(\"can not set 'in' or 'me' inside expression in C++ because of some really dumb reason\", INTERNAL_ERROR);\n\t\t\t}\n\t\t\t\n\t\t\tprog->pushBlock();\n\t\t\t\tprog->code(prog->getTypeCode(inRight->getReturnType()));\n\t\t\t\tprog->code(\" tmp = \");\n\t\t\t\tprog->pushExpr();\n\t\t\t\t\tinRight->addToProg(prog);\n\t\t\t\tprog->popExpr();\n\t\t\t\tprog->endln();\n\t\t\t\tauto subs=*getReturnType()->getAllSubTypes();\n\t\t\t\tfor (int i=0; i<(int)subs.size(); i++)\n\t\t\t\t{\n\t\t\t\t\tprog->name(subs[i].name);\n\t\t\t\t\tprog->code(\" = \");\n\t\t\t\t\tprog->code(\"tmp.\"+(*inRight->getReturnType()->getAllSubTypes())[i].name);\n\t\t\t\t\t//prog->pushExpr();\n\t\t\t\t\t\t//getElemFromTupleAction(inRight->getReturnType(), (*inRight->getReturnType()->getAllSubTypes())[i].name)->addToProg(var, voidAction, prog);\n\t\t\t\t\t//prog->popExpr();\n\t\t\t\t\tprog->endln();\n\t\t\t\t}\n\t\t\tprog->popBlock();\n\t\t}\n\t\telse\n\t\t*/\n\t\t{\n\t\t\tprog->declareVar(nameHint, getInRightType());\n\t\t\tprog->name(nameHint);\n\t\t\tprog->code(\" = \");\n\t\t\tprog->pushExpr();\n\t\t\tinRight->addToProg(prog);\n\t\t\tprog->popExpr();\n\t\t\t//if (prog->getExprLevel()==0)\n\t\t\t//\tprog->endln();\n\t\t}\n\t}\n\t\n\tstring getDescription()\n\t{\n\t\treturn str::putStringInTreeNodeBox(\"set \"+nameHint);\n\t}\n\t\nprivate:\n\t\n\tvoid ** stackPtrPtr;\n\tsize_t offset;\n};\n\nclass ConstGetAction: public ActionData\n{\npublic:\n\t\n\tConstGetAction(const void* in, Type typeIn, string textIn):\n\t\tActionData(typeIn, Void, Void)\n\t{\n\t\tdata=malloc(returnType->getSize());\n\t\tmemcpy(data, in, returnType->getSize());\n\t\t\n\t\tsetDescription(textIn);// + \" (\" + typeIn.toString() + \" literal)\");\n\t}\n\n\t~ConstGetAction()\n\t{\n\t\tfree(data);\n\t}\n\t\n\tvoid* execute(void* inLeft, void* inRight)\n\t{\n\t\tvoid* out=malloc(returnType->getSize());\n\t\tmemcpy(out, data, returnType->getSize());\n\t\treturn out;\n\t}\n\t\n\tvoid addToProg(Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\tif (getReturnType()==String)\n\t\t{\n\t\t\t//addToProgPnStr(prog);\n\t\t\t//prog->name(\"$pnStr\");\n\t\t\tprog->code(prog->getTypeCode(String));\n\t\t\tprog->pushExpr();\n\t\t\t\t\n\t\t\t\tauto sizeInfo=getReturnType()->getSubType(\"_size\");\n\t\t\t\tauto dataInfo=getReturnType()->getSubType(\"_data\");\n\t\t\t\tif (sizeInfo.type!=Int || dataInfo.type!=Byte->getPtr())\n\t\t\t\t{\n\t\t\t\t\tthrow PineconeError(\"ConstGetAction::addToProg failed to access string properties\", INTERNAL_ERROR);\n\t\t\t\t}\n\t\t\t\n\t\t\t\tprog->code(Int->getCppLiteral((char*)data+sizeInfo.offset, prog));\n\t\t\t\tprog->code(\", \");\n\t\t\t\t//prog->code(Int->getCppLiteral((char*)data+sizeInfo.offset, prog));\n\t\t\t\t//prog->code(\", (unsigned char*)\\\"\");\n\t\t\t\tprog->code(\"(unsigned char*)\\\"\");\n\t\t\t\tint len=*(int*)((char*)data+sizeInfo.offset);\n\t\t\t\tfor (int i=0; i<len; i++)\n\t\t\t\t{\n\t\t\t\t\tchar c=*((*(char**)((char*)data+dataInfo.offset))+i);\n\t\t\t\t\t\n\t\t\t\t\tif (c=='\"')\n\t\t\t\t\t{\n\t\t\t\t\t\tprog->code(\"\\\\\\\"\");\n\t\t\t\t\t}\n\t\t\t\t\telse if (c=='\\\\')\n\t\t\t\t\t{\n\t\t\t\t\t\tprog->code(\"\\\\\\\\\");\n\t\t\t\t\t}\n\t\t\t\t\telse if (c>=32 && c<=126)\n\t\t\t\t\t{\n\t\t\t\t\t\tprog->code(string()+c);\n\t\t\t\t\t}\n\t\t\t\t\telse if (c=='\\n')\n\t\t\t\t\t{\n\t\t\t\t\t\tprog->code(\"\\\\n\");\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tprog->code(str::charToCppStringLiteralEscaped(c));\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\tprog->code(\"\\\"\");\n\t\t\t\t\n\t\t\tprog->popExpr();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tprog->code(getReturnType()->getCppLiteral(data, prog));\n\t\t}\n\t}\n\t\n\tstring getDescription()\n\t{\n\t\treturn str::putStringInTreeNodeBox(description);\n\t}\n\t\nprivate:\n\t\n\tvoid* data;\n};\n\nAction varGetAction(size_t in, Type typeIn, string textIn)\n{\n\treturn Action(new VarGetAction(in, &stackPtr, typeIn, textIn));\n}\n\nAction varSetAction(size_t in, Type typeIn, string varNameIn)\n{\n\treturn Action(new VarSetAction(in, &stackPtr, typeIn, varNameIn));\n}\n\nAction globalGetAction(size_t in, Type typeIn, string textIn)\n{\n\treturn Action(new VarGetAction(in, &globalFramePtr, typeIn, textIn));\n}\n\nAction globalSetAction(size_t in, Type typeIn, string textIn)\n{\n\treturn Action(new VarSetAction(in, &globalFramePtr, typeIn, textIn));\n}\n\nAction constGetAction(const void* in, Type typeIn, string textIn, Namespace ns)\n{\n\tAction action=Action(new ConstGetAction(in, typeIn, textIn));\n\tif (ns)\n\t{\n\t\tAction copier=ns->getCopier(typeIn);\n\t\tif (copier)\n\t\t\taction=branchAction(voidAction, copier, action);\n\t}\n\treturn action;\n}\n"
  },
  {
    "path": "src/AllOperators.cpp",
    "content": "\n\n#include \"../h/AllOperators.h\"\n#include \"../h/ErrorHandler.h\"\n\n//shared_ptr<AllOperators> ops(nullptr);\nAllOperators* ops=nullptr;\n\nOperator opCreate(string textIn, int leftPrecedenceIn, int rightPrecedenceIn, bool overloadableIn);\n\nvoid AllOperators::init()\n{\n\t//ops=shared_ptr<AllOperators>(new AllOperators());\n\tops=new AllOperators();\n}\n\nAllOperators::AllOperators()\n{\t\n\t#undef DECLARE_OP\n\t\n\t//#define DECLARE_OP(name, text, left, right, overload) putOpInMap(name);\n\t\n\t#define DECLARE_OP(name, text, prece, input, overload) putOpInMap(name);\n\t\n\tALL_OPS;\n}\n\nvoid AllOperators::putOpInMap(Operator op)\n{\n\topsMap[op->getText()]=op;\n}\n\nvoid AllOperators::get(string text, vector<Operator>& out)\n{\n\tint start=0;\n\tint end=text.size();\n\t\n\twhile (start<int(text.size()))\n\t{\n\t\twhile (true)\n\t\t{\n\t\t\tif (end<=start)\n\t\t\t{\n\t\t\t\terror.log(\"unknown operator '\" + text + \"'\", SOURCE_ERROR);\n\t\t\t}\n\t\t\t\n\t\t\tauto i=opsMap.find(text.substr(start, end-start));\n\t\t\t\n\t\t\tif (i==opsMap.end())\n\t\t\t{\n\t\t\t\tend--;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tout.push_back(i->second);\n\t\t\t\tstart=end;\n\t\t\t\tend=text.size();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nbool AllOperators::isOpenBrac(Operator op)\n{\n\treturn op==openPeren || op==openSqBrac || op==openCrBrac;\n}\n\nbool AllOperators::isCloseBrac(Operator op)\n{\n\treturn op==closePeren || op==closeSqBrac || op==closeCrBrac;\n}\n\n/*\n// this is the only way to make an operator, and should only be called when setting up all the global operators at the top of Operator.cpp\nOperator opCreate(string textIn, int leftPrecedenceIn, int rightPrecedenceIn, bool overloadableIn)\n{\n\tOperator ptr(new OperatorData(textIn, leftPrecedenceIn, rightPrecedenceIn, overloadableIn));\n\t\n\t\n\tfor (auto i=OperatorData::precedenceLevels.begin();; i++)\n\t{\n\t\tif (i==OperatorData::precedenceLevels.end() || *i>leftPrecedenceIn)\n\t\t{\n\t\t\tOperatorData::precedenceLevels.insert(i, leftPrecedenceIn);\n\t\t\tbreak;\n\t\t}\n\t\telse if (*i==leftPrecedenceIn)\n\t\t\tbreak;\n\t}\n\t\n\tfor (auto i=OperatorData::precedenceLevels.begin();; i++)\n\t{\n\t\tif (i==OperatorData::precedenceLevels.end() || *i>rightPrecedenceIn)\n\t\t{\n\t\t\tOperatorData::precedenceLevels.insert(i, rightPrecedenceIn);\n\t\t\tbreak;\n\t\t}\n\t\telse if (*i==rightPrecedenceIn)\n\t\t\tbreak;\n\t}\n\t\n\t//operators.push_back(ptr);\n\treturn ptr;\n}\n*/\n\n\n"
  },
  {
    "path": "src/AstNode.cpp",
    "content": "#include \"../h/AstNode.h\"\n#include \"../h/Namespace.h\"\n#include \"../h/ErrorHandler.h\"\n#include \"../h/msclStringFuncs.h\"\n#include \"../h/utils/stringDrawing.h\"\n#include \"../h/AllOperators.h\"\n\n//AstNode astVoid=AstNode(new AstVoid);\n\nextern StackFrame stdLibStackFrame;\nextern Namespace globalNamespace;\n\nAction resolveLiteral(Token token);\n\nvoid AstNodeBase::copyToNode(AstNodeBase* other, bool copyCache)\n{\n\tother->inLeftType=inLeftType;\n\tother->inRightType=inRightType;\n\tother->nameHint=nameHint;\n\t\n\tif (copyCache)\n\t{\n\t\tother->action=action;\n\t\tother->returnType=returnType;\n\t\tother->dynamic=dynamic;\n\t\tother->ns=ns;\n\t\tother->inputHasBeenSet=inputHasBeenSet;\n\t}\n}\n\n/// List\n\nstring AstList::getString()\n{\n\tvector<string> data;\n\t\n\tfor (int i=0; i<int(nodes.size()); i++)\n\t{\n\t\tdata.push_back(nodes[i]->getString());\n\t}\n\t\n\treturn str::makeList(data);\n}\n\n/*void AstList::resolveReturnType()\n{\n\tif (nodes.empty())\n\t{\n\t\treturnType=Void;\n\t}\n\telse\n\t{\n\t\tnodes.back()->setInput(ns, dynamic, Void, Void);\n\t\treturnType=nodes.back()->getReturnType();\n\t}\n}*/\n\nvoid AstList::resolveAction()\n{\n\tif (!inLeftType->isVoid() || !inRightType->isVoid())\n\t{\n\t\tthrow PineconeError(\"AstList given non void input\", INTERNAL_ERROR, getToken());\n\t}\n\t\n\tns=ns->makeChild();\n\t\n\tfor (int i=0; i<int(nodes.size()); i++)\n\t{\n\t\tnodes[i]->setInput(ns, dynamic, Void, Void);\n\t\tnodes[i]->dealWithConstants();\n\t}\n\t\n\tvector<Action> actions;\n\t\n\tfor (int i=0; i<int(nodes.size()); i++)\n\t{\n\t\ttry\n\t\t{\n\t\t\tAction action=nodes[i]->getAction();\n\t\t\t\n\t\t\tif (i!=(int)nodes.size()-1)\n\t\t\t\taction=ns->wrapInDestroyer(action);\n\t\t\t\n\t\t\tactions.push_back(action);\n\t\t}\n\t\tcatch (PineconeError err)\n\t\t{\n\t\t\terr.log();\n\t\t}\n\t}\n\t\n\taction=listAction(actions, *ns->getDestroyerActions());\n}\n\n\n/// Function body\n\nstring AstFuncBody::getString()\n{\n\tvector<string> data;\n\t\n\tdata.push_back(\"function\");\n\t\n\tvector<string> types={leftTypeNode->getString(), rightTypeNode->getString(), returnTypeNode->getString()};\n\t\n\tdata.push_back(str::makeList(types));\n\t\n\tdata.push_back(bodyNode->getString());\n\t\n\treturn str::makeList(data);\n}\n\nAstNode AstFuncBody::makeCopyWithSpecificTypes(Type leftInType, Type rightInType)\n{\n\tType leftWhatevType=leftTypeNode->getReturnType()->getSubType();\n\tType rightWhatevType=rightTypeNode->getReturnType()->getSubType();\n\t\n\tif (!leftInType->matches(leftWhatevType) || !rightInType->matches(rightWhatevType))\n\t{\n\t\treturn nullptr;\n\t}\n\t\n\tAstNode actualLeftTypeNode;\n\tAstNode actualRightTypeNode;\n\t\n\tif (leftWhatevType->isWhatev())\n\t{\n\t\tactualLeftTypeNode=AstTypeType::make(leftWhatevType->actuallyIs(leftInType));\n\t}\n\telse\n\t{\n\t\tactualLeftTypeNode=leftTypeNode->makeCopy(false);\n\t}\n\t\n\tif (rightWhatevType->isWhatev())\n\t{\n\t\tactualRightTypeNode=AstTypeType::make(rightWhatevType->actuallyIs(rightInType));\n\t}\n\telse\n\t{\n\t\tactualRightTypeNode=rightTypeNode->makeCopy(false);\n\t}\n\t\n\tAstNode out=make(move(actualLeftTypeNode), move(actualRightTypeNode), returnTypeNode->makeCopy(false), bodyNode->makeCopy(false));\n\tout->nameHint=nameHint;\n\tout->setInput(ns, dynamic, Void, Void);\n\treturn out;\n}\n\nvoid AstFuncBody::resolveAction()\n{\n\tsetTypesInput();\n\tNamespace subNs=ns->makeChildAndFrame(nameHint.empty()?\"unnamed function's namespace\":nameHint+\"'s namespace\");\n\tsubNs->setInput(leftTypeNode->getReturnType()->getSubType(), rightTypeNode->getReturnType()->getSubType());\n\tbodyNode->setInput(subNs, true, Void, Void);\n\tType funcReturnType=returnTypeNode->getReturnType()->getSubType();\n\tif (funcReturnType->isWhatev())\n\t{\n\t\tfuncReturnType=funcReturnType->actuallyIs(bodyNode->getReturnType());\n\t}\n\taction=functionAction(bodyNode->makeCopy(true), funcReturnType, subNs->getStackFrame());\n}\n\n\n/// Expression\n\nstring AstExpression::getString()\n{\n\tstring leftStr;\n\tif (!leftIn->isVoid())\n\t{\n\t\tleftStr=leftIn->getString();\n\t}\n\t\n\tstring centerStr=center->getString();\n\t\n\tstring rightStr;\n\tif (!rightIn->isVoid())\n\t{\n\t\trightStr=rightIn->getString();\n\t}\n\t\n\treturn str::makeRootUpBinaryTree(centerStr, \"\", \"\", leftStr, rightStr);\n}\n\nvoid AstExpression::resolveAction()\n{\n\tif (!inLeftType->isVoid() || !inRightType->isVoid())\n\t{\n\t\tthrow PineconeError(\"AstExpression given non void input\", INTERNAL_ERROR, getToken());\n\t}\n\t\n\tif (rightIn->isType())\n\t{\n\t\tthrow PineconeError(\"types must be declared as constants\", SOURCE_ERROR, rightIn->getToken());\n\t}\n\telse if (center->isType() || center->isFunctionWithOutput() || leftIn->isType())\n\t{\n\t\tthrow PineconeError(\"a function implementation got into an expression node somehow\", INTERNAL_ERROR, center->getToken());\n\t}\n\telse\n\t{\n\t\tleftIn->setInput(ns, dynamic, Void, Void);\n\t\trightIn->setInput(ns, dynamic, Void, Void);\n\t\t\n\t\tcenter->setInput(ns, dynamic, leftIn->getReturnType(), rightIn->getReturnType());\n\t\t\n\t\t//error.log(\"left: \" + leftIn->getString(), JSYK);\n\t\t//error.log(\"center: \" + center->getString(), JSYK);\n\t\t//error.log(\"right: \" + rightIn->getString(), JSYK);\n\t\t//error.log(\"\", JSYK);\n\t\t\n\t\taction=branchAction(leftIn->getAction(), center->getAction(), rightIn->getAction());\n\t}\n\t\n\tif (action->nameHint.empty())\n\t\taction->nameHint=nameHint;\n}\n\n\n/// Const Expression\n\nstring AstConstExpression::getString()\n{\n\tstring centerStr=center->getString();\n\t\n\tstring rightStr;\n\tif (!rightIn->isVoid())\n\t{\n\t\trightStr=rightIn->getString();\n\t}\n\t\n\treturn str::makeRootUpBinaryTree(centerStr, \"\", \"const\", \"\", rightStr);\n}\n\nvoid AstConstExpression::resolveConstant()\n{\n\tif (!inLeftType->isVoid() || !inRightType->isVoid())\n\t{\n\t\tthrow PineconeError(\"AstConstExpression given non void input\", INTERNAL_ERROR, getToken());\n\t}\n\t\n\t//leftIn->setInput(ns, Void, Void);\n\trightIn->setInput(ns, false, Void, Void);\n\t\n\t//error.log(\"resolveAction called for \"+getString(), JSYK);\n\t\n\tns->addNode(move(rightIn->makeCopy(true)), center->token->getText());\n\t\n\t/*\n\tAction rightAction=rightIn->getAction();\n\t\n\tvoid * val=rightAction->execute(nullptr, nullptr);\n\t\n\t//center->setInput(ns, false, Void, rightIn->getReturnType());\n\t\n\tAction valAction=constGetAction(val, rightAction->getReturnType(), \"const expression\");\n\t\n\tns->addAction(valAction, center->token->getText());*/\n}\n\n\n/// Operation with input\n\nstring AstOpWithInput::getString()\n{\n\tstring left;\n\t\n\tvector<string> data;\n\t\n\tfor (int i=0; i<int(leftIn.size()); i++)\n\t{\n\t\tdata.push_back(leftIn[i]->getString());\n\t}\n\t\n\tif (data.size()==1)\n\t\tleft=data[0];\n\telse if (data.size()>1)\n\t\tleft=str::makeList(data);\n\t\n\tdata.clear();\n\t\n\tstring right;\n\t\n\tfor (int i=0; i<int(rightIn.size()); i++)\n\t{\n\t\tdata.push_back(rightIn[i]->getString());\n\t}\n\t\n\tif (data.size()==1)\n\t\tright=data[0];\n\telse if (data.size()>1)\n\t\tright=str::makeList(data);\n\t\n\treturn str::makeRootUpBinaryTree(str::putStringInTreeNodeBox(token->getText()), \"\", \"\", left, right);\n}\n\nvoid AstOpWithInput::resolveAction()\n{\n\tif (token->getOp()==ops->ifOp)\n\t{\n\t\tfor (int i=0; i<int(leftIn.size()); i++)\n\t\t\tleftIn[i]->setInput(ns, dynamic, Void, Void);\n\t\t\t\n\t\tfor (int i=0; i<int(rightIn.size()); i++)\n\t\t\trightIn[i]->setInput(ns, dynamic, Void, Void);\n\t\t\t\n\t\tif (leftIn.empty())\n\t\t{\n\t\t\tthrow PineconeError(\"'?' must have a conditional to its left\", SOURCE_ERROR, token);\n\t\t}\n\t\telse if (leftIn.size()!=1)\n\t\t{\n\t\t\tthrow PineconeError(\"'?' can only have one conditional to its left\", SOURCE_ERROR, token);\n\t\t}\n\t\t\n\t\tAction condition=leftIn[0]->getAction();\n\t\t\n\t\tif (rightIn.empty())\n\t\t{\n\t\t\tthrow PineconeError(\"'?' must have a statement to its right\", SOURCE_ERROR, token);\n\t\t}\n\t\telse if (rightIn.size()<=2)\n\t\t{\n\t\t\tAction a;\n\t\t\t\n\t\t\ttry\n\t\t\t{\n\t\t\t\ta=rightIn[0]->getAction();\n\t\t\t}\n\t\t\tcatch (PineconeError err)\n\t\t\t{\n\t\t\t\terr.log();\n\t\t\t\ta=voidAction;\n\t\t\t}\n\t\t\t\n\t\t\tif (rightIn.size()==1)\n\t\t\t{\n\t\t\t\taction=ifAction(condition, a);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tAction e;\n\t\t\t\t\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\te=rightIn[1]->getAction();\n\t\t\t\t}\n\t\t\t\tcatch (PineconeError err)\n\t\t\t\t{\n\t\t\t\t\terr.log();\n\t\t\t\t\te=voidAction;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\taction=ifElseAction(condition, a, e);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthrow PineconeError(\"'?' can only have 1 or 2 '|' seporated expressions to its right\", SOURCE_ERROR, token);\n\t\t}\n\t}\n\telse if (token->getOp()==ops->loop)\n\t{\n\t\tbool usesSubNS=false;\n\t\t\n\t\tif (leftIn.size()==3)\n\t\t{\n\t\t\tns=ns->makeChild();\n\t\t\tusesSubNS=true;\n\t\t}\n\t\t\t\n\t\tfor (int i=0; i<int(leftIn.size()); i++)\n\t\t\tleftIn[i]->setInput(ns, dynamic, Void, Void);\n\t\t\t\n\t\tfor (int i=0; i<int(rightIn.size()); i++)\n\t\t\trightIn[i]->setInput(ns, dynamic, Void, Void);\n\t\t\t\n\t\tAction initAction=nullptr, conditionAction, endAction, bodyAction;\n\t\t\n\t\tif (rightIn.size()>1)\n\t\t{\n\t\t\tthrow PineconeError(\"'@' followed by multiple expressions\", SOURCE_ERROR, token);\n\t\t}\n\t\t\n\t\tif (leftIn.size()==0)\n\t\t{\n\t\t\tthrow PineconeError(\"condition needed before '@'\", SOURCE_ERROR, token);\n\t\t}\n\t\telse if (leftIn.size()==1)\n\t\t{\n\t\t\tconditionAction=leftIn[0]->getAction();\n\t\t\tendAction=voidAction;\n\t\t}\n\t\telse if (leftIn.size()==2)\n\t\t{\n\t\t\tconditionAction=leftIn[0]->getAction();\n\t\t\tendAction=leftIn[1]->getAction();\n\t\t}\n\t\telse if (leftIn.size()==3)\n\t\t{\n\t\t\tinitAction=leftIn[0]->getAction();\n\t\t\tconditionAction=leftIn[1]->getAction();\n\t\t\tendAction=leftIn[2]->getAction();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthrow PineconeError(\"chain of length \"+to_string(leftIn.size())+\"preceding '@', it should be length 1-3\", SOURCE_ERROR, token);\n\t\t}\n\t\t\n\t\tif (rightIn.empty())\n\t\t{\n\t\t\tbodyAction=voidAction;\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttry\n\t\t\t{\n\t\t\t\tbodyAction=rightIn[0]->getAction();\n\t\t\t}\n\t\t\tcatch (PineconeError err)\n\t\t\t{\n\t\t\t\terr.log();\n\t\t\t\tbodyAction=voidAction;\n\t\t\t}\n\t\t}\n\t\t\n\t\tvector<Action> actions;\n\t\t\n\t\tif (initAction)\n\t\t\tactions.push_back(ns->wrapInDestroyer(initAction));\n\t\t\n\t\tactions.push_back(ns->wrapInDestroyer(loopAction(conditionAction, endAction, bodyAction)));\n\t\t\n\t\taction=usesSubNS ?\n\t\t\t\taction=listAction(actions, *ns->getDestroyerActions())\n\t\t\t:\n\t\t\t\taction=listAction(actions, {})\n\t\t;\n\t}\n\telse if (token->getOp()==ops->andOp || token->getOp()==ops->orOp)\n\t{\n\t\tif (leftIn.size()>1 || rightIn.size()>1)\n\t\t{\n\t\t\tthrow PineconeError(\"'\"+token->getOp()->getText()+\"' can not be sent '|' separated sequence\", SOURCE_ERROR, getToken());\n\t\t}\n\t\t\n\t\tif (leftIn.size()!=1 || rightIn.size()!=1)\n\t\t{\n\t\t\tthrow PineconeError(\"'\"+token->getOp()->getText()+\"' must be given a left and right input\", SOURCE_ERROR, getToken());\n\t\t}\n\t\t\n\t\tleftIn[0]->setInput(ns, dynamic, Void, Void);\n\t\trightIn[0]->setInput(ns, dynamic, Void, Void);\n\t\t\n\t\tAction leftAction=leftIn[0]->getAction();\n\t\tAction rightAction=rightIn[0]->getAction();\n\t\t\n\t\tif (leftAction->getReturnType()!=Bool)\n\t\t{\n\t\t\tthrow PineconeError(\"'\"+token->getOp()->getText()+\"' can only be used with Bools\", SOURCE_ERROR, leftIn[0]->getToken());\n\t\t}\n\t\t\n\t\tif (rightAction->getReturnType()!=Bool)\n\t\t{\n\t\t\tthrow PineconeError(\"'\"+token->getOp()->getText()+\"' can only be used with Bools\", SOURCE_ERROR, rightIn[0]->getToken());\n\t\t}\n\t\t\n\t\tif (token->getOp()==ops->andOp)\n\t\t{\n\t\t\taction=andAction(leftAction, rightAction);\n\t\t}\n\t\telse // (token->getOp()==ops->orOp)\n\t\t{\n\t\t\taction=orAction(leftAction, rightAction);\n\t\t}\n\t}\n\telse if (token->getOp()==ops->rightArrow)\n\t{\n\t\tthrow PineconeError(\"AstOpWithInput::resolveAction called for token '\"+token->getOp()->getText()+\"', which it shouldn't have been\", INTERNAL_ERROR, token);\n\t}\n\telse\n\t{\n\t\tthrow PineconeError(\"AstOpWithInput made with bad token '\"+token->getText()+\"'\", INTERNAL_ERROR, token);\n\t}\n}\n\nbool AstOpWithInput::isFunctionWithOutput()\n{\n\treturn token->getOp()==ops->rightArrow && leftIn.size()==1 && rightIn.size()==1;\n}\n\n\n/// Token\n\nstring AstToken::getString()\n{\n\treturn str::putStringInTreeNodeBox(token->getText());\n}\n\nvoid AstToken::resolveAction()\n{\n\t//error.log(\"resolveAction called for token \"+token->getText(), JSYK, token);\n\t\n\tif (token->getType()==TokenData::IDENTIFIER || token->getType()==TokenData::OPERATOR)\n\t{\n\t\tif (token->getOp() && !token->getOp()->isOverloadable())\n\t\t{\n\t\t\tthrow PineconeError(\"non overloadable operator in AstToken, it should have been removed and processed by the parser\", INTERNAL_ERROR, token);\n\t\t}\n\t\t\n\t\t/*\n\t\tif (inLeftType->getType()==TypeBase::TUPLE && inLeftType->getSubType(token->getText()).type!=nullptr)\n\t\t{\n\t\t\tif (inRightType->isVoid())\n\t\t\t{\n\t\t\t\taction=getElemFromTupleAction(inLeftType, token->getText());\n\t\t\t\treturn;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthrow PineconeError(\"sorry, Pinecone does not yet support mutating tuples\", SOURCE_ERROR, token);\n\t\t\t}\n\t\t}\n\t\t*/\n\t\t\n\t\taction=ns->getActionForTokenWithInput(token, inLeftType, inRightType, dynamic, true, token);\n\t\t\n\t\t/*\n\t\ttry\n\t\t{\n\t\t\t//error.log(\"looking for \"+token->getText()+\" in\\n\"+ns->getStringWithParents(), JSYK, token);\n\t\t\taction=ns->getActionForTokenWithInput(token, inLeftType, inRightType, dynamic);\n\t\t}\n\t\tcatch (IdNotFoundError err)\n\t\t{\n\t\t\tif (token->getType()==TokenData::OPERATOR)\n\t\t\t{\n\t\t\t\tthrow PineconeError(\"unknown overload for \"+inLeftType->getString()+\" \"+token->getText()+\" \"+inRightType->getString()+\"'\", SOURCE_ERROR, token);\n\t\t\t}\n\t\t\telse if (token->getType()==TokenData::IDENTIFIER)\n\t\t\t{\n\t\t\t\tvector<Action> actions;\n\t\t\t\tns->getActions(token->getText(), actions, dynamic);\n\t\t\t\t\n\t\t\t\tif (actions.size()>0) // if there are actions with the requested name that didn't match the type\n\t\t\t\t{\n\t\t\t\t\tstring posibleInputs=\"the following is the inputs it can take:\";\n\t\t\t\t\t\n\t\t\t\t\tfor (int i=0; i<(int)actions.size(); i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tposibleInputs+=\"\\n    \";\n\t\t\t\t\t\tposibleInputs+=actions[i]->getInLeftType()->getString()+\" . \"+actions[i]->getInRightType()->getString()+\" -> \"+actions[i]->getReturnType()->getString();\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tthrow PineconeError(\n\t\t\t\t\t\t\"'\"+token->getText()+\"' can not take input of type \"+\n\t\t\t\t\t\tinLeftType->getString()+\" . \"+inRightType->getString()+\"\\n\"+\n\t\t\t\t\t\tposibleInputs,\n\t\t\t\t\t\tSOURCE_ERROR, token);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (inRightType->getType()==TypeBase::METATYPE)\n\t\t\t{\n\t\t\t\tthrow PineconeError(\"metatype handeling in \"+FUNC+\" not yet implemented\", INTERNAL_ERROR, token);\n\t\t\t}\n\t\t\telse if (inRightType->isVoid())\n\t\t\t{\n\t\t\t\t//throw PineconeError(\"unknown identifier '\"+token->getText()+\"' (var can not be made bc right in type is \"+type->getString()+\")\", SOURCE_ERROR, token);\n\t\t\t\tthrow PineconeError(\"unknown identifier '\"+token->getText()+\"'\", SOURCE_ERROR, token);\n\t\t\t}\n\t\t\telse if (!inRightType->isCreatable())\n\t\t\t{\n\t\t\t\tthrow PineconeError(\"cannot create variable '\"+token->getText()+\"' of type {\"+inRightType->getString()+\"}\", SOURCE_ERROR, token);\n\t\t\t}\n\t\t\t\n\t\t\tns->addVar(inRightType, token->getText());\n\t\t\t\n\t\t\ttry\n\t\t\t{\n\t\t\t\taction=ns->getActionForTokenWithInput(token, inLeftType, inRightType, dynamic);\n\t\t\t}\n\t\t\tcatch (IdNotFoundError err)\n\t\t\t{\n\t\t\t\tthrow err.toPineconeError(token);\n\t\t\t}\n\t\t}\n\t\t*/\n\t}\n\telse if (token->getType()==TokenData::LITERAL || token->getType()==TokenData::STRING_LITERAL)\n\t{\n\t\tif (!inLeftType->isVoid() || !inRightType->isVoid())\n\t\t{\n\t\t\tthrow PineconeError(\"a literal can not be given an input\", SOURCE_ERROR, token);\n\t\t}\n\t\t\n\t\taction=resolveLiteral(token);\n\t}\n\telse\n\t{\n\t\tthrow PineconeError(\"AstToken givin invalid token '\"+token->getText()+\"' of type \"+TokenData::typeToString(token->getType()), INTERNAL_ERROR, token);\n\t}\n}\n\n\n/// Tuple\n\nstring AstTuple::getString()\n{\n\tvector<string> data;\n\t\n\tfor (int i=0; i<int(nodes.size()); i++)\n\t{\n\t\tdata.push_back(nodes[i]->getString());\n\t}\n\t\n\treturn str::makeList(data);\n}\n\nvoid AstTuple::resolveAction()\n{\n\tvector<Action> actions;\n\t\n\tfor (int i=0; i<int(nodes.size()); i++)\n\t{\n\t\tnodes[i]->setInput(ns, dynamic, Void, Void);\n\t\tactions.push_back(nodes[i]->getAction());\n\t}\n\t\n\taction=makeTupleAction(actions);\n}\n\n\n/// TokenType\n\nstring AstTokenType::getString()\n{\n\treturn \"{\"+token->getText()+\"}\";\n}\n\nvoid AstTokenType::resolveReturnType()\n{\n\treturnType=ns->getType(token->getText(), true, token)->getMeta();\n}\n\n\n/// TupleType\n\nstring AstTupleType::getString()\n{\n\tstring out;\n\t\n\tout+=\"AstTupleType{\";\n\t\n\tfor (int i=0; i<int(subTypes.size()); i++)\n\t{\n\t\tauto type=&subTypes[i];\n\t\t\n\t\tif (type->name)\n\t\t{\n\t\t\tout+=type->name->getText()+\": \";\n\t\t}\n\t\t\n\t\tout+=type->type->getString();\n\t\t\n\t\tif (i<int(subTypes.size())-1)\n\t\t{\n\t\t\tout+=\", \";\n\t\t}\n\t}\n\t\n\tout+=\"}\";\n\t\n\treturn out;\n}\n\nvoid AstTupleType::resolveReturnType()\n{\n\tTupleTypeMaker maker;\n\t\n\tfor (unsigned i=0; i<subTypes.size(); i++)\n\t{\n\t\tsubTypes[i].type->setInput(ns, false, Void, Void);\n\t\t\n\t\tif (subTypes[i].name)\n\t\t{\n\t\t\tmaker.add(subTypes[i].name->getText(), subTypes[i].type->getReturnType()->getSubType());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tmaker.add(subTypes[i].type->getReturnType()->getSubType());\n\t\t}\n\t}\n\t\n\treturnType=maker.get(true)->getMeta();\n}\n\n\n"
  },
  {
    "path": "src/CppProgram.cpp",
    "content": "#include \"../h/CppProgram.h\"\n#include \"../h/msclStringFuncs.h\"\n\n#include <map>\n#include <unordered_set>\n\nstring getValidCppId(string in)\n{\n\tstring cpp;\n\t\n\tif (in.empty())\n\t\tin=\"no_name\";\n\t\n\tint start=0;\n\t\n\t// all this should work with unicode (although it may inject random (but valid) characters into the C++ names)\n\tdo\n\t{\n\t\tint i=start;\n\t\t\n\t\tfor (; i<int(in.size()) && (\n\t\t\t\t(in[i]>='a' && in[i]<='z') ||\n\t\t\t\t(in[i]>='A' && in[i]<='Z') ||\n\t\t\t\t(in[i]>='0' && in[i]<='9') ||\n\t\t\t\tin[i]=='_'\n\t\t\t); i++) {}\n\t\t\n\t\tif (i!=start)\n\t\t{\n\t\t\tif (in[start]>='0' && in[start]<='9')\n\t\t\t\tcpp+=\"_\";\n\t\t\tcpp+=in.substr(start, i-start);\n\t\t}\n\t\t\n\t\tstart=i+1;\n\t\t\n\t} while (start<int(in.size()));\n\t\n\treturn cpp;\n}\n\n\n/// Name Container\n\nCppNameContainer::CppNameContainer()\n{\n\t\n}\n\nshared_ptr<CppNameContainer> CppNameContainer::makeRoot()\n{\n\tauto out=shared_ptr<CppNameContainer>(new CppNameContainer());\n\tout->parent=nullptr;\n\treturn out;\n}\n\nshared_ptr<CppNameContainer> CppNameContainer::makeChild()\n{\n\tauto out=shared_ptr<CppNameContainer>(new CppNameContainer());\n\tchildren.push_back(out);\n\tout->parent=this;\n\treturn out;\n}\n\nvoid CppNameContainer::addPn(const string& pn, const string& cppNameHint)\n{\n\tstring validCppHint;\n\t\n\tif (cppNameHint==\"<- the value of that pn string please\")\n\t\tvalidCppHint=getValidCppId(pn);\n\telse if (!cppNameHint.empty())\n\t\tvalidCppHint=getValidCppId(cppNameHint);\n\t\n\tif (pnToCppMap.find(pn)!=pnToCppMap.end())\n\t{\n\t\tthrow PineconeError(\"Tried to add '\"+pn+\"' as a pn name to a CppNameContainer but that pn name already exists\", INTERNAL_ERROR);\n\t}\n\t\n\t// now we need to find a unique C++ name, the pinecone name will almost always be unique, but there may be cases where Pinecone treats scope differently or uses a keyword or something\n\t\n\tstring cpp;\n\t\n\tif (validCppHint.empty())\n\t{\n\t\tcpp=getUniqueString(\n\t\t\t\t\"nm\",\n\t\t\t\t[this](string in) -> bool\n\t\t\t\t{\n\t\t\t\t\treturn !hasCpp(in);\n\t\t\t\t},\n\t\t\t\ttrue\n\t\t\t);\n\t}\n\telse\n\t{\n\t\tcpp=getUniqueString(\n\t\t\t\tvalidCppHint,\n\t\t\t\t[this](string in) -> bool\n\t\t\t\t{\n\t\t\t\t\treturn !hasCpp(in);\n\t\t\t\t},\n\t\t\t\tfalse\n\t\t\t);\n\t}\n\t\n\tpnToCppMap[pn]=cpp;\n\tcppSet.insert(cpp);\n}\n\nvoid CppNameContainer::reserveCpp(const string& cpp, bool ignoreCollisions)\n{\n\tif (!ignoreCollisions && hasCpp(cpp))\n\t{\n\t\tthrow PineconeError(\"called CppNameContainer::reserveCpp with id '\"+cpp+\"', which already exists\", INTERNAL_ERROR);\n\t}\n\t\n\tcppSet.insert(cpp);\n}\n\nbool CppNameContainer::hasPnMe(const string& pn)\n{\n\treturn pnToCppMap.find(pn)!=pnToCppMap.end();\n}\n\nbool CppNameContainer::hasPn(const string& pn)\n{\n\treturn hasPnMe(pn) || (parent && parent->hasPn(pn));\n}\n\nbool CppNameContainer::hasCpp(const string& cpp)\n{\n\treturn hasCppMe(cpp) || hasCppUp(cpp) || hasCppDown(cpp);\n}\n\nbool CppNameContainer::hasCppMe(const string& cpp)\n{\n\treturn cppSet.find(cpp)!=cppSet.end();\n}\n\nbool CppNameContainer::hasCppUp(const string& cpp)\n{\n\treturn parent && (parent->hasCppMe(cpp) || parent->hasCppUp(cpp));\n}\n\nbool CppNameContainer::hasCppDown(const string& cpp)\n{\n\tfor (auto i: children)\n\t{\n\t\tif (i->hasCppMe(cpp) || i->hasCppDown(cpp))\n\t\t\treturn true;\n\t}\n\t\n\treturn false;\n}\n\nstring CppNameContainer::getCpp(const string& pn)\n{\n\tauto result=pnToCppMap.find(pn);\n\t\n\tif (result==pnToCppMap.end())\n\t{\n\t\tif (parent)\n\t\t\treturn parent->getCpp(pn);\n\t\telse\n\t\t\tthrow PineconeError(\"could not find C++ equivalent of '\"+pn+\"' in CppNameContainer::getCppForPn\", INTERNAL_ERROR);\n\t}\n\telse\n\t\treturn result->second;\n}\n\n\n/// funcs\n\nCppFuncBase::CppFuncBase(string prototypeIn, shared_ptr<CppNameContainer> myNames, bool returnsValIn)\n{\n\tprototype=prototypeIn;\n\tnamespaceStack.push_back(myNames);\n\tfreshLine=true;\n\treturnsVal=returnsValIn;\n}\n\nvoid CppFuncBase::code(const string& in)\n{\n\tif (freshLine)\n\t{\n\t\tsource+=indentString(in, indent, blockLevel);\n\t\tfreshLine=(in.back()=='\\n');\n\t}\n\telse if (searchInString(in, \"\\n\")>0)\n\t{\n\t\tsource+=\"\\n\"+indentString(in, indent, blockLevel);\n\t\tif (in.back()!='\\n')\n\t\t\tsource+=\"\\n\";\n\t\tfreshLine=true;\n\t}\n\telse\n\t{\n\t\tsource+=in;\n\t\tfreshLine=(in.back()=='\\n');\n\t}\n}\n\nvoid CppFuncBase::name(const string& in)\n{\n\tcode(namespaceStack.back()->getCpp(in));\n}\n\nvoid CppFuncBase::line(const string& in)\n{\n\tcode(in);\n\tendln();\n}\n\nvoid CppFuncBase::endln()\n{\n\tif (exprLevel>0)\n\t{\n\t\tthrow PineconeError(\"non zero expression level when ending line in C++ program, code so far:\\n\"+indentString(source), INTERNAL_ERROR);\n\t}\n\telse if (freshLine && (source.size()<2 || source[source.size()-2]==';' || source[source.size()-2]=='}' || source[source.size()-2]=='{'))\n\t{\n\t\t// do nothing\n\t\t\n\t\t//source+=indentString(\"\\n\", indent, blockLevel);\n\t}\n\telse\n\t{\n\t\tsource+=\";\\n\";\n\t}\n\t\n\tfreshLine=true;\n}\n\nvoid CppFuncBase::comment(const string& in)\n{\n\tif (searchInString(in, \"\\n\")>=0)\n\t{\n\t\tsource+=indentString(\"\\n/*\\n\"+in+\"\\n*/\\n\", indent, blockLevel);\n\t\tfreshLine=true;\n\t}\n\telse if (exprLevel>0 || !freshLine)\n\t{\n\t\tsource+=\"/* \"+in+\" */\";\n\t\tfreshLine=false;\n\t}\n\telse\n\t{\n\t\tsource+=indentString(\"// \"+in+\"\\n\", indent, blockLevel);\n\t\tfreshLine=true;\n\t}\n};\n\nvoid CppFuncBase::pushExpr()\n{\n\tcode(\"(\");\n\texprLevel++;\n\tfreshLine=false;\n}\n\nvoid CppFuncBase::popExpr()\n{\n\tif (exprLevel<=0)\n\t{\n\t\tthrow PineconeError(\"CppProgram::popExpression called with zero expressionLevel\", INTERNAL_ERROR);\n\t}\n\t\n\tcode(\")\");\n\texprLevel--;\n\tfreshLine=false;\n}\n\nvoid CppFuncBase::pushBlock()\n{\n\tif (exprLevel>0)\n\t{\n\t\tthrow PineconeError(\"CppProgram::pushBlock called when expressionLevel was not zero\", INTERNAL_ERROR);\n\t}\n\t\n\t{\n\t\tcode(\"{\\n\");\n\t\tnamespaceStack.push_back(namespaceStack.back()->makeChild());\n\t\tblockLevel++;\n\t\tfreshLine=true;\n\t}\n}\n\nvoid CppFuncBase::popBlock()\n{\n\t\n\t{\n\t\tif (blockLevel<=0)\n\t\t{\n\t\t\tthrow PineconeError(\"CppProgram::popBlock called with zero indentationLevel\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\tblockLevel--;\n\t\tnamespaceStack.pop_back();\n\t\tcode(\"}\\n\");\n\t\tfreshLine=true;\n\t}\n}\n\nstring CppFuncBase::pnToCpp(const string& in)\n{\n\treturn namespaceStack.back()->getCpp(in);\n}\n\n\n/// program\n\nCppProgram::CppProgram()\n{\n\t//funcs = unique_ptr<std::map<string, CppFunc>>(new std::map<string, CppFunc>());\n\tglobalNames=CppNameContainer::makeRoot();\n\tsetup();\n}\n\nvoid CppProgram::setup()\n{\n\tglobalTopCode+=\"// this C++ code is transpiled from Pinecone\\n\";\n\tglobalTopCode+=\"// Pinecone v\"+to_string(VERSION_X)+\".\"+to_string(VERSION_Y)+\".\"+to_string(VERSION_Z)+\" was used\\n\";\n\tglobalIncludesCode+=\"#include <string.h>\\n\";\n\tglobalIncludesCode+=\"#include <stdlib.h>\\n\";\n\tglobalIncludesCode+=\"#include <stdio.h>\\n\";\n\t\n\tglobalVarCode+=\"int argc = 0;\\n\";\n\tglobalVarCode+=\"char** argv = 0;\\n\";\n\t\n\tvector<string> cppReservedWords\n\t{\n\t\t// from C\n\t\t\"auto\", \"const\", \"double\", \"float\", \"int\", \"short\", \"struct\", \"unsigned\", \"break\",\n\t\t\"continue\", \"else\", \"for\", \"long\", \"signed\", \"switch\", \"void\", \"case\", \"default\",\n\t\t\"enum\", \"goto\", \"register\", \"sizeof\", \"typedef\", \"volatile\", \"char\", \"do\", \"extern\",\n\t\t\"if\", \"return\", \"static\", \"union\", \"while\",\n\t\t\n\t\t// from old C++\n\t\t\"asm\", \"dynamic_cast\", \"namespace\", \"reinterpret_cast\", \"try\", \"bool\", \"explicit\",\n\t\t\"new\", \"static_cast\", \"typeid\", \"catch\", \"false\", \"operator\", \"template\", \"typename\",\n\t\t\"class\", \"friend\", \"private\", \"this\", \"using\", \"const_cast\", \"inline\", \"public\",\n\t\t\"throw\", \"virtual\", \"delete\", \"mutable\", \"protected\", \"true\", \"wchar_t\", \n\t\t\n\t\t// from C++11\n\t\t\"and\", \"bitand\", \"compl\", \"not_eq\", \"or_eq\", \"xor_eq\", \"and_eq\", \"bitor\", \"not\", \"or\",\n\t\t\"xor\",\n\t\t\n\t\t// something else\n\t\t\"endl\", \"INT_MIN\", \"std\", \"INT_MAX\", \"MAX_RAND\", \"NULL\",\n\t\t\n\t\t// my custom\n\t\t\"main\", \"argc\", \"argv\",\n\t};\n\t/*\n\t{\n\t\t\"and\", \"and_eq\", \"asm\", \"auto\", \"bitand\", \"bitor\", \"bool\", \"break\", \"case\", \"catch\", \"char\", \"class\", \"const\", \"const_cast\",\n\t\t\"continue\", \"default\", \"delete\", \"do\", \"double\", \"dynamic_cast\", \"else\", \"enum\", \"explicit\", \"export\", \"extern\", \"false\", \"float\",\n\t\t\"for\", \"friend\", \"goto\", \"if\", \"inline\", \"int\", \"long\", \"mutable\", \"namespace\", \"new\", \"not\", \"not_eq\", \"operator\", \"or\", \"or_eq\",\n\t\t\"private\", \"protected\", \"public\", \"register\", \"reinterpret_cast\", \"return\", \"short\", \"signed\", \"sizeof\", \"static\", \"static_cast\",\n\t\t\"struct\", \"switch\", \"template\", \"this\", \"throw\", \"true\", \"try\", \"typedef\", \"typeid\", \"typename\", \"union\", \"unsigned\", \"using\",\n\t\t\"virtual\", \"void\", \"volatile\", \"wchar_t\", \"while\", \"xor\", \"xor_eq\", \"\"\n\t};\n\t*/\n\t\t\n\tfor (auto i: cppReservedWords)\n\t{\n\t\tglobalNames->reserveCpp(i);\n\t}\n\t\n\tpushFunc(string(\"_main\"), Void, Void, Void);\n}\n\nstring CppProgram::getTypeCode(Type in)\n{\n\tswitch (in->getType())\n\t{\n\tcase TypeBase::VOID:\n\t\treturn \"void\";\n\t\t\n\tcase TypeBase::DUB:\n\t\treturn \"double\";\n\t\t\n\tcase TypeBase::INT:\n\t\treturn \"int\";\n\t\n\tcase TypeBase::BYTE:\n\t\treturn \"unsigned char\";\n\t\n\tcase TypeBase::BOOL:\n\t\treturn \"bool\";\n\t\t\n\tcase TypeBase::PTR:\n\t\tif (in->getSubType()->isWhatev())\n\t\t\treturn \"void *\";\n\t\telse\n\t\t\treturn getTypeCode(in->getSubType())+\" *\";\n\t\t\n\tcase TypeBase::TUPLE:\n\t{\n\t\tif (in->getAllSubTypes()->size()==1)\n\t\t\treturn getTypeCode((*in->getAllSubTypes())[0].type);\n\t\t\n\t\tstring compact=\"{\"+in->getCompactString()+\"}\";\n\t\t\n\t\tif (!globalNames->hasPn(compact))\n\t\t{\n\t\t\tglobalNames->addPn(compact, in->nameHint);\n\t\t\tstring code;\n\t\t\tcode+=\"struct \";\n\t\t\tcode+=globalNames->getCpp(compact);\n\t\t\tcode+=\"\\n{\\n\";\n\t\t\tfor (auto i: *in->getAllSubTypes())\n\t\t\t{\n\t\t\t\tcode+=indentString(getTypeCode(i.type)+\" \"+i.name+\";\\n\", indent);\n\t\t\t}\n\t\t\t\n\t\t\tcode+=\"\\n\";\n\t\t\tcode+=indentString(globalNames->getCpp(compact), indent);\n\t\t\tcode+=\"() {}\\n\";\n\t\t\t\n\t\t\tcode+=\"\\n\";\n\t\t\tauto conNames=globalNames->makeChild();\n\t\t\tcode+=indentString(globalNames->getCpp(compact), indent);\n\t\t\tcode+=\"(\";\n\t\t\tbool first=true;\n\t\t\tfor (auto i: *in->getAllSubTypes())\n\t\t\t{\n\t\t\t\tif (first) first=false; else code+=\", \";\n\t\t\t\tconNames->addPn(\"+\"+i.name+\"_in\");\n\t\t\t\tcode+=getTypeCode(i.type)+\" \"+conNames->getCpp(\"+\"+i.name+\"_in\");\n\t\t\t}\n\t\t\tcode+=\")\\n\";\n\t\t\tcode+=indentString(\"{\\n\", indent);\n\t\t\tfor (auto i: *in->getAllSubTypes())\n\t\t\t{\n\t\t\t\tcode+=indentString(i.name+\" = \"+conNames->getCpp(\"+\"+i.name+\"_in\")+\";\\n\", indent, 2);\n\t\t\t}\n\t\t\tcode+=indentString(\"}\\n\", indent);\n\t\t\t\n\t\t\tcode+=\"};\\n\";\n\t\t\t\n\t\t\tif (!globalTypesCode.empty())\n\t\t\t\tglobalTypesCode+=\"\\n\";\n\t\t\tglobalTypesCode+=code;\n\t\t}\n\t\t\n\t\treturn globalNames->getCpp(compact);\n\t}\n\t\n\tdefault:\n\t\tthrow PineconeError(\"CppProgram::getTypeCode called with invalid type \"+(TypeBase::getString(in->getType())), INTERNAL_ERROR);\n\t}\n}\n\nvoid CppProgram::declareVar(const string& nameIn, Type typeIn, string initialValue)\n{\n\t/*\n\tCppNameContainer* names=&*activeFunc->namespaceStack.back();\n\t\n\twhile (names)\n\t{\n\t\tif (names->hasPnMe(nameIn))\n\t\t\treturn;\n\t\t\n\t\tnames=names->getParent();\n\t}\n\t*/\n\t\n\tif (isMain())\n\t{\n\t\tdeclareGlobal(nameIn, typeIn, initialValue);\n\t\treturn;\n\t}\n\t\n\tif (activeFunc->namespaceStack.back()->hasPn(nameIn))\n\t{\n\t\treturn;\n\t}\n\t\n\tactiveFunc->namespaceStack.back()->addPn(nameIn);\n\tactiveFunc->namespaceStack[0]->reserveCpp(pnToCpp(nameIn), true);\n\t\n\tactiveFunc->varDeclareSource+=getTypeCode(typeIn)+\" \"+pnToCpp(nameIn);\n\tif (!initialValue.empty())\n\t{\n\t\tactiveFunc->varDeclareSource+=\" = \"+initialValue;\n\t}\n\tactiveFunc->varDeclareSource+=\";\\n\";\n}\n\nvoid CppProgram::declareGlobal(const string& nameIn, Type typeIn, string initialValue)\n{\n\tif (globalNames->hasPn(nameIn))\n\t\treturn;\n\t\n\tstring code;\n\tcode+=getTypeCode(typeIn);\n\tcode+=\" \";\n\tglobalNames->addPn(nameIn);\n\tcode+=globalNames->getCpp(nameIn);\n\tif (!initialValue.empty())\n\t{\n\t\tcode+=\" = \";\n\t\tcode+=initialValue;\n\t}\n\tcode+=\";\\n\";\n\t\n\tglobalVarCode+=code;\n}\n\nvoid CppProgram::addHeadCode(const string& code)\n{\n\tglobalIncludesCode += code + \"\\n\";\n}\n\nbool CppProgram::hasFunc(const string& name)\n{\n\treturn funcs.find(name)!=funcs.end();\n}\n\nvoid CppProgram::addFunc(const string& name, vector<std::pair<string, string>> args, string returnType, string contents)\n{\n\tif (hasFunc(name))\n\t{\n\t\tthrow PineconeError(\"called CppProgram::addFunc with function name '\"+name+\"', which already exists\", INTERNAL_ERROR);\n\t}\n\t\n\tglobalNames->addPn(name, name);\n\t\n\tstring cppName=globalNames->getCpp(name);\n\t\n\tstring prototype;\n\t\n\tprototype+=returnType;\n\t\n\tprototype+=\" \"+cppName+\"(\";\n\t\n\tfor (int i=0; i<int(args.size()); i++)\n\t{\n\t\tif (i)\n\t\t\tprototype+=\", \";\n\t\t\n\t\tprototype+=args[i].first;\n\t\t\n\t\tprototype+=\" \";\n\t\t\n\t\tprototype+=args[i].second;\n\t}\n\t\n\tprototype+=\")\";\n\t\n\tauto func=CppFunc(new CppFuncBase(prototype, globalNames->makeChild(), (returnType!=\"\" && returnType!=\"void\")));\n\tfuncs[name]=func;\n\tfunc->code(contents);\n}\n\n//void CppProgram::pushFunc(const string& name, vector<std::pair<string, string>> args, Type returnType)\nvoid CppProgram::pushFunc(const string& name, const string& cppNameHint, Type leftIn, Type rightIn, Type returnType)\n{\n\tif (hasFunc(name))\n\t{\n\t\tthrow PineconeError(\"called CppProgram::pushFunc with function name '\"+name+\"', which already exists\", INTERNAL_ERROR);\n\t}\n\t\n\tglobalNames->addPn(name, cppNameHint);\n\t\n\tstring cppName=globalNames->getCpp(name);\n\t\n\tauto funcNames=globalNames->makeChild();\n\t\n\tstring prototype;\n\t\n\tprototype+=getTypeCode(returnType);\n\t\n\tprototype+=\" \"+cppName+\"(\";\n\t\n\tbool keepTuplesTogether=true;\n\t\n\tif (keepTuplesTogether)\n\t{\n\t\tif (leftIn->isCreatable())\n\t\t{\n\t\t\tprototype+=getTypeCode(leftIn)+\" me\";\n\t\t\tfuncNames->addPn(\"me\");\n\t\t}\n\t\t\n\t\tif (rightIn->isCreatable())\n\t\t{\n\t\t\tif (leftIn->isCreatable())\n\t\t\t\tprototype+=\", \";\n\t\t\t\n\t\t\tprototype+=getTypeCode(rightIn)+\" in\";\n\t\t\tfuncNames->addPn(\"in\");\n\t\t}\n\t}\n\telse\n\t{\n\t\tvector<std::pair<string, string>> args;\n\t\t\n\t\tif (leftIn->getType()==TypeBase::TUPLE)\n\t\t{\n\t\t\tfor (auto i: *leftIn->getAllSubTypes())\n\t\t\t{\n\t\t\t\targs.push_back({getTypeCode(i.type), i.name});\n\t\t\t}\n\t\t}\n\t\telse if (!leftIn->isCreatable())\n\t\t{\n\t\t\t// do nothing\n\t\t}\n\t\telse\n\t\t{\n\t\t\targs.push_back({getTypeCode(leftIn), \"me\"});\n\t\t}\n\t\t\n\t\tif (rightIn->getType()==TypeBase::TUPLE)\n\t\t{\n\t\t\tfor (auto i: *rightIn->getAllSubTypes())\n\t\t\t{\n\t\t\t\targs.push_back({getTypeCode(i.type), i.name});\n\t\t\t}\n\t\t}\n\t\telse if (!rightIn->isCreatable())\n\t\t{\n\t\t\t// do nothing\n\t\t}\n\t\telse\n\t\t{\n\t\t\targs.push_back({getTypeCode(rightIn), \"in\"});\n\t\t}\n\t\t\n\t\tfor (int i=0; i<int(args.size()); i++)\n\t\t{\n\t\t\tif (i)\n\t\t\t\tprototype+=\", \";\n\t\t\t\n\t\t\tprototype+=args[i].first;\n\t\t\t\n\t\t\tprototype+=\" \";\n\t\t\t\n\t\t\tfuncNames->addPn(args[i].second, args[i].second);\n\t\t\t\n\t\t\tprototype+=funcNames->getCpp(args[i].second);\n\t\t}\n\t}\n\t\n\tprototype+=\")\";\n\t\n\tactiveFunc=CppFunc(new CppFuncBase(prototype, funcNames, returnType->isCreatable()));\n\tfuncs[name]=activeFunc;\n\tfuncStack.push_back(name);\n}\n\nvoid CppProgram::popFunc()\n{\n\tif (activeFunc->getExprLevel()>0 || !activeFunc->getIfFreshLine() || activeFunc->getBlockLevel()>0)\n\t{\n\t\tthrow PineconeError(\"called CppProgram::popFunc when function wasn't ready\", INTERNAL_ERROR);\n\t}\n\t\n\tfuncStack.pop_back();\n\t\n\tif (funcStack.empty())\n\t{\n\t\tthrow PineconeError(\"called CppProgram::popFunc too many times\", INTERNAL_ERROR);\n\t}\n\t\n\tactiveFunc=funcs[funcStack.back()];\n}\n\nstring CppProgram::getCppCode()\n{\n\tstring out;\n\t\n\tif (!globalTopCode.empty())\n\t\tout+=globalTopCode+\"\\n\";\n\t\n\tif (!globalIncludesCode.empty())\n\t\tout+=globalIncludesCode+\"\\n\";\n\t\n\tif (!globalTypesCode.empty())\n\t\tout+=globalTypesCode+\"\\n\";\n\t\n\tif (funcs.size()>1)\n\t{\n\t\tfor (auto i: funcs)\n\t\t{\n\t\t\tif (i.first!=\"main\")\n\t\t\t\tout+=i.second->getPrototype()+\";\\n\";\n\t\t}\n\t\t\n\t\tout+=\"\\n\";\n\t}\n\t\n\tif (!globalVarCode.empty())\n\t\tout+=globalVarCode+\"\\n\";\n\t\n\tfor (auto i: funcs)\n\t{\n\t\tout+=i.second->getPrototype();\n\t\t\n\t\tstring funcSrc=i.second->getSource();\n\t\t\n\t\tif (funcSrc.size()<2)\n\t\t{\n\t\t\tout+=\"\\n{\\n\\t// empty function\\n}\\n\\n\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (i.second->getIfReturnsVal() && funcSrc[0]!='{' && searchInString(funcSrc, \";\")==int(funcSrc.size())-2)\n\t\t\t\tfuncSrc=\"return \"+funcSrc;\n\t\t\tout+=\"\\n{\\n\";\n\t\t\tif (!i.second->varDeclareSource.empty())\n\t\t\t\tout+=indentString(i.second->varDeclareSource+\"\\n\", indent);\n\t\t\tout+=indentString(funcSrc, indent);\n\t\t\tif (!out.empty() && out.back()!='\\n')\n\t\t\t\tout+=\";\\n\";\n\t\t\t//if (i.first==\"main\")\n\t\t\t//\tout+=indentString(\"return 0;\\n\", indent);\n\t\t\t//if (out.substr(out.size()-2, 2)!=\";\\n\")\n\t\t\t//\tout+=\";\\n\";\n\t\t\tout+=\"}\\n\\n\";\n\t\t}\n\t}\n\t\n\tout+=\n\"int main(int argcIn, char** argvIn)\\n\\\n{\\n\\\n\targc = argcIn;\\n\\\n\targv = argvIn;\\n\\\n\tif (argc >= 2 && strcmp(argv[1], \\\"--running-from-pinecone\\\") == 0)\\n\\\n\t{\\n\\\n\t\targc -= 2;\\n\\\n\t\tif (argc == 0)\\n\\\n\t\t\targv = 0;\\n\\\n\t\telse\\n\\\n\t\t\targv += 2;\\n\\\n\t}\\n\\\n\t_main();\\n\\\n\treturn 0;\\n\\\n}\\n\";\n\t\n\treturn out;\n}\n\n\n"
  },
  {
    "path": "src/ErrorHandler.cpp",
    "content": "\n#include \"../h/ErrorHandler.h\"\n#include \"../h/msclStringFuncs.h\"\n#include \"../h/SourceFile.h\"\n\n#include <iostream>\n\nusing std::cout;\nusing std::endl;\n\nErrorHandler error;\n\nstring ErrorHandler::priorityToStr(ErrorPriority in)\n{\n\tswitch (in)\n\t{\n\tcase SOURCE_ERROR:\n\t\treturn \"error\";\n\t\tbreak;\n\t\t\n\tcase SOURCE_WARNING:\n\t\treturn \"warning\";\n\t\tbreak;\n\t\t\n\tcase JSYK:\n\t\treturn \"jsyk\";\n\t\tbreak;\n\t\t\n\tcase INTERNAL_ERROR:\n\t\treturn \"INTERNAL ERROR\";\n\t\tbreak;\n\t\t\n\tcase RUNTIME_ERROR:\n\t\treturn \"runtime error\";\n\t\tbreak;\n\t\t\n\tdefault:\n\t\treturn \"UNKNOWN PRIORITY LEVEL\";\n\t\tbreak;\n\t}\n}\n\nvoid ErrorHandler::log(string msg, ErrorPriority priority, Token token)\n{\n\tif (priority==SOURCE_ERROR || priority==INTERNAL_ERROR || priority==RUNTIME_ERROR)\n\t\terrorHasBeenLogged=true;\n\t\n\t// gcc style\n\t//if (token)\n\t//\tcout << token->getFile() << \":\" << token->getLine() << \":\" << token->getCharPos() << \": \";\n\t\n\t//cout << priorityToStr(priority) << \": \" << msg << endl;\n\t\n\t// Pinecone style\n\t\n\tcout << priorityToStr(priority);\n\t\n\tif (token)\n\t{\n\t\tcout << \" in '\" << token->getFile()->getFilename() << \"' on line \" << token->getLine() << \":\" << endl;\n\t\tcout << indentString(msg, \"    \") << endl;\n\t\t\n\t\tstring line=token->getFile()->getLine(token->getLine());\n\t\t\n\t\tint wspace=0;\n\t\tfor (; wspace<int(line.size()) && (line[wspace]==' ' || line[wspace]=='\\t' || line[wspace]=='\\n'); wspace++) {}\n\t\t\n\t\tstring arrows=\"\";\n\t\tfor (int i=0; i<token->getCharPos()-1-wspace; i++)\n\t\t\tarrows+=\" \";\n\t\tfor (int i=0; i<int(token->getText().size()); i++)\n\t\t\tarrows+=\"^\";\n\t\t\n\t\tcout << indentString(\"\"+line.substr(wspace, string::npos)+\"\\n\"+arrows, \"    \") << endl;\n\t}\n\telse\n\t{\n\t\tcout << \": \" << msg << endl;\n\t}\n}\n\nvoid ErrorHandler::msg(string in)\n{\n\tcout << \"message: \" << in << endl;\n}\n\nPineconeError::PineconeError(string msgIn, ErrorPriority priorityIn, Token tokenIn)\n{\n\tmsg=msgIn;\n\tpriority=priorityIn;\n\ttoken=tokenIn;\n}\n\nvoid PineconeError::log()\n{\n\terror.log(msg, priority, token);\n}\n"
  },
  {
    "path": "src/Lexer.cpp",
    "content": "#include \"../h/Token.h\"\n#include \"../h/ErrorHandler.h\"\n#include \"../h/Operator.h\"\n#include \"../h/AllOperators.h\"\n#include \"../h/SourceFile.h\"\n\n#include <vector>\nusing std::vector;\n\n#include <unordered_map>\nusing std::unordered_map;\n\nclass CharClassifier\n{\npublic:\n\tenum Type\n\t{\n\t\tWHITESPACE,\n\t\tLINE_BREAK,\n\t\tNEWLINE,\n\t\tLETTER,\n\t\tDIGIT,\n\t\tOPERATOR,\n\t\tSTRING_QUOTE,\n\t\tSINGLE_LINE_COMMENT,\n\t\tMULTI_LINE_COMMENT_START,\n\t\tMULTI_LINE_COMMENT_END,\n\t\tUNKNOWN,\n\t};\n\t\n\tstatic inline TokenData::Type getTokenType(CharClassifier::Type type, TokenData::Type previousType);\n\t\n\tinline CharClassifier::Type get(shared_ptr<SourceFile> file, int i);\n\t\nprivate:\n\tvoid setUp();\n\t\nprivate:\n\tunordered_map<char, CharClassifier::Type> hm;\n\tbool hasSetUp=false;\n};\n\nCharClassifier charClassifier;\n\nvoid CharClassifier::setUp()\n{\n\thm[' ']=WHITESPACE;\n\thm['\\t']=WHITESPACE;\n\t\n\thm['\\r']=WHITESPACE; // ignore '\\r' character on windows style line ending\n\t\t\n\thm['\\n']=NEWLINE;\n\thm[';']=LINE_BREAK;\n\t\n\tfor (char c='a'; c<='z'; ++c)\n\t\thm[c]=LETTER;\n\t\n\tfor (char c='A'; c<='Z'; ++c)\n\t\thm[c]=LETTER;\n\t\n\thm['_']=LETTER;\n\t\n\tfor (char c='0'; c<='9'; ++c)\n\t\thm[c]=DIGIT;\n\t\n\thm['#']=SINGLE_LINE_COMMENT;\n\t\n\thm['\"']=STRING_QUOTE;\n\t\n\tunordered_map<string, Operator>& opsMap=ops->getOpsMap();\n\t\n\tfor (auto i=opsMap.begin(); i!=opsMap.end(); ++i)\n\t{\n\t\tstring str=(*i).first;\n\t\tfor (unsigned j=0; j<str.size(); j++)\n\t\t{\n\t\t\thm[str[j]]=OPERATOR;\n\t\t}\n\t}\n\t\n\thasSetUp=true;\n}\n\ninline CharClassifier::Type CharClassifier::get(shared_ptr<SourceFile> file, int index)\n{\n\t//\tset up the first time this function is called\n\tif (!hasSetUp)\n\t\tsetUp();\n\t\n\t//\tchack fo multi line comments in a special way, because they are multi character\n\t\n\tswitch ((*file)[index])\n\t{\n\tcase '/':\n\t\tif (index<int(file->size())-1 && (*file)[index+1]=='/')\n\t\t\treturn MULTI_LINE_COMMENT_START;\n\t\tbreak;\n\t\t\n\tcase '\\\\':\n\t\tif (index>0 && (*file)[index-1]=='\\\\')\n\t\t\treturn MULTI_LINE_COMMENT_END;\n\t\tbreak;\n\t\t\n\tcase '.': // allow a . to be a digit character only if it is followed by a digit\n\t\tif (index<int(file->size())-1)\n\t\t{\n\t\t\tauto i=hm.find((*file)[index+1]);\n\t\t\n\t\t\tif (i!=hm.end() && i->second==DIGIT)\n\t\t\t\treturn DIGIT;\n\t\t}\n\t\tbreak;\n\t}\n\t\n\t//\thandle all other cases using the hashmap\n\tchar c=(*file)[index];\n\t\n\tauto i=hm.find(c);\n\t\n\tif (i==hm.end())\n\t\treturn UNKNOWN;\n\telse\n\t\treturn i->second;\n}\n\ninline TokenData::Type CharClassifier::getTokenType(CharClassifier::Type type, TokenData::Type previousType)\n{\n\tif (previousType==TokenData::LINE_COMMENT)\n\t{\n\t\tif (type==NEWLINE)\n\t\t\treturn TokenData::WHITESPACE;\n\t\telse\n\t\t\treturn TokenData::LINE_COMMENT;\n\t}\n\telse if (previousType==TokenData::BLOCK_COMMENT)\n\t{\n\t\tif (type==MULTI_LINE_COMMENT_END)\n\t\t\treturn TokenData::WHITESPACE;\n\t\telse\n\t\t\treturn TokenData::BLOCK_COMMENT;\n\t}\n\telse if (previousType==TokenData::STRING_LITERAL)\n\t{\n\t\tif (type==STRING_QUOTE)\n\t\t\treturn TokenData::WHITESPACE;\n\t\telse\n\t\t\treturn TokenData::STRING_LITERAL;\n\t\t\n\t}\n\t\n\tswitch (type)\n\t{\n\t\n\tcase SINGLE_LINE_COMMENT:\n\t\treturn TokenData::LINE_COMMENT;\n\t\n\tcase MULTI_LINE_COMMENT_START:\n\t\treturn TokenData::BLOCK_COMMENT;\n\t\n\tcase MULTI_LINE_COMMENT_END:\n\t\terror.log(\"block comment end without start\", SOURCE_ERROR);\n\t\treturn TokenData::UNKNOWN;\n\t\t\n\tcase WHITESPACE:\n\t\treturn TokenData::WHITESPACE;\n\t\t\n\tcase LINE_BREAK:\n\tcase NEWLINE:\n\t\treturn TokenData::LINE_END;\n\t\t\n\tcase OPERATOR:\n\t\treturn TokenData::OPERATOR;\n\t\t\n\tcase LETTER:\n\tcase DIGIT:\n\t\tif (previousType==TokenData::IDENTIFIER || previousType==TokenData::LITERAL)\n\t\t\treturn previousType;\n\t\telse if (type==DIGIT)\n\t\t\treturn TokenData::LITERAL;\n\t\telse\n\t\t\treturn TokenData::IDENTIFIER;\n\t\t\n\tcase STRING_QUOTE:\n\t\treturn TokenData::STRING_LITERAL;\n\t\t\n\tdefault:\n\t\treturn TokenData::UNKNOWN;\n\t\t\n\t}\n}\n\nvoid lexString(shared_ptr<SourceFile> file, vector<Token>& tokens)\n{\n\tstring tokenTxt;\n\tint line=1;\n\tint charPos=1;\n\t\n\tTokenData::Type type=TokenData::WHITESPACE;\n\t\n\tfor (int i=0; i<file->size(); i++)\n\t{\n\t\tCharClassifier::Type charType=charClassifier.get(file, i);\n\t\tTokenData::Type newType=CharClassifier::getTokenType(charType, type);\n\t\t\n\t\tif (newType!=type)\n\t\t{\n\t\t\tif (!tokenTxt.empty())\n\t\t\t{\n\t\t\t\tif (type==TokenData::OPERATOR)\n\t\t\t\t{\n\t\t\t\t\tvector<Operator> opMatches;\n\t\t\t\t\tops->get(tokenTxt, opMatches);\n\t\t\t\t\t\n\t\t\t\t\tfor (auto op: opMatches)\n\t\t\t\t\t{\n\t\t\t\t\t\ttokens.push_back(makeToken(op->getText(), file, line, charPos-tokenTxt.size(), type, op));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (type==TokenData::LINE_COMMENT || type==TokenData::BLOCK_COMMENT)\n\t\t\t\t{\n\t\t\t\t\t// do nothing\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tToken token=makeToken(tokenTxt, file, line, charPos-tokenTxt.size(), type);\n\t\t\t\t\t\n\t\t\t\t\tif (type==TokenData::UNKNOWN)\n\t\t\t\t\t{\n\t\t\t\t\t\tPineconeError(\"invalid token '\"+tokenTxt+\"'\", SOURCE_ERROR, token).log();\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\ttokens.push_back(token);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\ttokenTxt=\"\";\n\t\t}\n\t\t\n\t\tif (newType!=TokenData::WHITESPACE && newType!=TokenData::LINE_END)\n\t\t{\n\t\t\tif (newType==TokenData::STRING_LITERAL && (*file)[i]=='\\\\')\n\t\t\t{\n\t\t\t\ti++;\n\t\t\t\tif ((*file)[i]=='n')\n\t\t\t\t\ttokenTxt+='\\n';\n\t\t\t\telse if ((*file)[i]=='\"')\n\t\t\t\t\ttokenTxt+='\"';\n\t\t\t\telse if ((*file)[i]=='t')\n\t\t\t\t\ttokenTxt+='\\t';\n\t\t\t\telse if ((*file)[i]=='\\\\')\n\t\t\t\t\ttokenTxt+='\\\\';\n\t\t\t\telse\n\t\t\t\t\tthrow PineconeError(string()+\"invalid escape character '\\\\\"+(*file)[i]+\"'\", SOURCE_ERROR, makeToken(tokenTxt+(*file)[i], file, line, charPos-tokenTxt.size(), type));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttokenTxt+=(*file)[i];\n\t\t\t}\n\t\t}\n\t\t\n\t\ttype=newType;\n\t\t\n\t\tif ((*file)[i]=='\\n')\n\t\t{\n\t\t\tline++;\n\t\t\tcharPos=1;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcharPos++;\n\t\t}\n\t}\n}\n\n\n\n\n"
  },
  {
    "path": "src/Namespace.cpp",
    "content": "#include \"../h/Namespace.h\"\n#include \"../h/StackFrame.h\"\n#include \"../h/msclStringFuncs.h\"\n#include \"../h/ErrorHandler.h\"\n#include \"../h/utils/stringNumConversion.h\"\n\nvoid NamespaceData::IdMap::add(string key, AstNode node)\n{\n\tauto i=nodes.find(key);\n\t\n\tif (i==nodes.end())\n\t{\n\t\tnodes[key]=vector<AstNode>();\n\t}\n\t\n\tnodes[key].push_back(move(node));\n}\n\nvoid NamespaceData::IdMap::get(string key, vector<AstNodeBase*>& out)\n{\n\tauto matches=nodes.find(key);\n\t\n\tif (matches!=nodes.end())\n\t{\n\t\tfor (unsigned i=0; i<matches->second.size(); i++)\n\t\t{\n\t\t\tout.push_back(&*matches->second[i]);\n\t\t}\n\t}\n}\n\nNamespace NamespaceData::makeRootNamespace()\n{\n\treturn Namespace(new NamespaceData(Namespace(nullptr), shared_ptr<StackFrame>(new StackFrame()), \"root\"));\n}\n\nNamespace NamespaceData::makeChild()\n{\n\treturn Namespace(new NamespaceData(shared_from_this(), stackFrame));\n}\n\nNamespace NamespaceData::makeChildAndFrame(string nameIn)\n{\n\treturn Namespace(new NamespaceData(shared_from_this(), shared_ptr<StackFrame>(new StackFrame()), nameIn));\n}\n\nNamespaceData::NamespaceData(Namespace parentIn, shared_ptr<StackFrame> stackFrameIn, string nameIn)\n{\n\tparent=parentIn;\n\tstackFrame=stackFrameIn;\n\tmyName=nameIn;\n}\n\nstring NamespaceData::getString()\n{\n\t/*string out;\n\t\n\tout+=\"normal functions:\\n\";\n\t\n\tfor (auto i: actions)\n\t{\n\t\tout+=\"\\t\";\n\t\t\n\t\tout+=i.first;\n\t\t\n\t\tif (i.second.size()>1)\n\t\t\tout+=\" (\" + to_string(i.second.size()) + \" overloads)\";\n\t\t\n\t\tout+=\"\\n\";\n\t}\n\t\n\tout+=\"\\nconverters:\\n\";\n\t\n\tfor (auto i: converters)\n\t{\n\t\tout+=\"\\t\";\n\t\t\n\t\tout+=i.first->getString();\n\t\t\n\t\tif (i.second.size()>1)\n\t\t\tout+=\" (\" + to_string(i.second.size()) + \" overloads)\";\n\t\t\n\t\tout+=\"\\n\";\n\t}\n\t\n\tout+=\"\\noperators:\\n\";\n\t\n\tfor (auto i: operators)\n\t{\n\t\tout+=\"\\t\";\n\t\tout+=i.first->getText();\n\t\t\n\t\tif (i.second.size()>1)\n\t\t\tout+=\" (\" + to_string(i.second.size()) + \" overloads)\";\n\t\t\n\t\tout+=\"\\n\";\n\t}\n\t\n\tout+=\"\\ntypes:\\n\";\n\tfor (auto i: types)\n\t{\n\t\tout+=\"\\t\";\n\t\tout+=i.second->getString() + \" (\" + i.second->getString() + \")\";\n\t\tout+=\"\\n\";\n\t}\n\t\n\treturn out;*/\n\t\n\treturn \"NamespaceData::getString not yet implemented\";\n}\n\nstring NamespaceData::getStringWithParents()\n{\n\tauto ptr=shared_from_this();\n\t\n\tstring out;\n\t\n\twhile (ptr)\n\t{\n\t\tout=putStringInBox(ptr->getString()+\"\\n\"+out, ptr->myName);\n\t\tptr=ptr->parent;\n\t}\n\t\n\treturn out;\n}\n\nvoid NamespaceData::setInput(Type left, Type right)\n{\n\tif (parent && parent->getStackFrame()==stackFrame)\n\t{\n\t\terror.log(\"called \"+FUNC+\" on namespace that is not the root of a stack frame, thus it can not get input\", INTERNAL_ERROR);\n\t\treturn;\n\t}\n\t\n\tstackFrame->setInput(left, right);\n\t\n\t//if (!left->isVoid())\n\tif (left->isCreatable())\n\t{\n\t\tstring leftName=\"me\";\n\t\tsize_t leftOffset=stackFrame->getLeftOffset();\n\t\tAction leftGetAction=varGetAction(leftOffset, left, leftName);\n\t\tAction leftSetAction=varSetAction(leftOffset, left, leftName);\n\t\taddNode(AstActionWrapper::make(leftGetAction), leftName);\n\t\taddNode(AstActionWrapper::make(leftSetAction), leftName);\n\t}\n\t\n\t//if (!right->isVoid())\n\tif (right->isCreatable())\n\t{\n\t\tstring rightName=\"in\";\n\t\tsize_t rightOffset=stackFrame->getRightOffset();\n\t\tAction rightGetAction=varGetAction(rightOffset, right, rightName);\n\t\tAction rightSetAction=varSetAction(rightOffset, right, rightName);\n\t\taddNode(AstActionWrapper::make(rightGetAction), rightName);\n\t\taddNode(AstActionWrapper::make(rightSetAction), rightName);\n\t}\n}\n\nAction NamespaceData::addVar(Type type, string name)\n{\n\tsize_t offset=stackFrame->getSize();\n\tstackFrame->addMember(type);\n\t\n\tAction getAction;\n\tAction setAction;\n\tAction copyAction;\n\t\n\tNamespace top=shared_from_this();\n\t\n\twhile(top->parent)\n\t{\n\t\ttop=top->parent;\n\t}\n\t\n\tif (stackFrame!=top->stackFrame)\n\t{\n\t\tgetAction=varGetAction(offset, type, name);\n\t\tsetAction=varSetAction(offset, type, name);\n\t}\n\telse\n\t{\n\t\tgetAction=globalGetAction(offset, type, name);\n\t\tsetAction=globalSetAction(offset, type, name);\n\t}\n\t\n\tcopyAction=getCopier(type);\n\t\n\tif (copyAction)\n\t{\n\t\tdynamicActions.add(name, AstActionWrapper::make(branchAction(voidAction, copyAction, getAction)));\n\t}\n\telse\n\t{\n\t\tdynamicActions.add(name, AstActionWrapper::make(getAction));\n\t}\n\t\n\tdynamicActions.add(name, AstActionWrapper::make(setAction));\n\t\n\tAction destructor=getDestroyer(type);\n\t\n\tif (destructor)\n\t{\n\t\tdestructorActions.push_back(branchAction(voidAction, destructor, getAction));\n\t}\n\t\n\treturn setAction;\n}\n\nvoid NamespaceData::addNode(AstNode node, string id)\n{\n\tif (node->nameHint.empty())\n\t{\n\t\tnode->nameHint=id;\n\t\tnode->nameHintSet();\n\t}\n\t\n\tif (node->isType())\n\t{\n\t\ttypes.add(id, move(node));\n\t}\n\t/*\n\telse if (id==\"__destroy__\")\n\t{\n\t\tAction action=node->getAction();\n\t\tif (action->getInRightType()->isVoid() || !action->getInLeftType()->isVoid() || !action->getReturnType()->isVoid())\n\t\t{\n\t\t\tthrow PineconeError(\"incorrect type signiture for destroyer\", SOURCE_ERROR, node->getToken());\n\t\t}\n\t\tdestructors.add(str::ptrToUniqueStr(&*action->getInRightType(), 6), move(node));\n\t}\n\telse if (id==\"__copy__\")\n\t{\n\t\tAction action=node->getAction();\n\t\tif (action->getInRightType()->isVoid() || !action->getInLeftType()->isVoid() || action->getReturnType()!=action->getInRightType())\n\t\t{\n\t\t\tthrow PineconeError(\"incorrect type signiture for copier\", SOURCE_ERROR, node->getToken());\n\t\t}\n\t\tcopiers.add(str::ptrToUniqueStr(&*action->getReturnType(), 6), move(node));\n\t}\n\t*/\n\telse\n\t{\n\t\t// if the left or the right is a Whatev and the types match up\n\t\tif (node->canBeWhatev())\n\t\t{\n\t\t\twhatevActions.add(id, move(node));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tactions.add(id, move(node));\n\t\t}\n\t}\n}\n\nType NamespaceData::getType(string name, bool throwSourceError, Token tokenForError)\n{\n\tvector<AstNodeBase*> results;\n\t\n\ttypes.get(name, results);\n\t\n\tif (results.empty())\n\t{\n\t\tif (parent)\n\t\t\treturn parent->getType(name, throwSourceError, tokenForError);\n\t\telse if (throwSourceError)\n\t\t\tthrow PineconeError(\"'\"+name+\"' type not found\", SOURCE_ERROR);\n\t\telse\n\t\t\treturn nullptr;\n\t}\n\telse if (results.size()!=1)\n\t{\n\t\tthrow PineconeError(\"namespace has multiple defenitions of the same type '\"+name+\"'\", INTERNAL_ERROR);\n\t}\n\telse if (results[0]->getReturnType()->getType()!=TypeBase::METATYPE)\n\t{\n\t\tthrow PineconeError(\"node returning non meta type stored in namespace type map for type '\"+name+\"'\", INTERNAL_ERROR);\n\t}\n\telse\n\t{\n\t\treturn results[0]->getReturnType()->getSubType();\n\t}\n}\n\nAction NamespaceData::getDestroyer(Type type)\n{\n\treturn getActionForTokenWithInput(makeToken(\"__destroy__\"), Void, type, false, false, nullptr);\n\t\n\t/*\n\tvector<AstNodeBase*> nodes;\n\t\n\tdestructors.get(str::ptrToUniqueStr(&*type, 6), nodes);\n\t\n\tif (nodes.empty())\n\t{\n\t\tif (parent)\n\t\t\treturn parent->getDestroyer(type);\n\t\telse\n\t\t\treturn nullptr;\n\t}\n\telse if (nodes.size()>1)\n\t{\n\t\tthrow PineconeError(\"multiple destroyers for a single type in a single namespace\", INTERNAL_ERROR);\n\t}\n\telse\n\t{\n\t\treturn nodes[0]->getAction();\n\t}\n\t*/\n}\n\nAction NamespaceData::wrapInDestroyer(Action in)\n{\n\tAction destroyer=getDestroyer(in->getReturnType());\n\t\n\treturn destroyer ?\n\t\t\tbranchAction(voidAction, destroyer, in)\n\t\t:\n\t\t\tin\n\t;\n}\n\nAction NamespaceData::getCopier(Type type)\n{\n\treturn getActionForTokenWithInput(makeToken(\"__copy__\"), Void, type, false, false, nullptr);\n\t\n\t/*\n\tvector<AstNodeBase*> nodes;\n\t\n\tcopiers.get(str::ptrToUniqueStr(&*type, 6), nodes);\n\t\n\tif (nodes.empty())\n\t{\n\t\tif (parent)\n\t\t\treturn parent->getCopier(type);\n\t\telse\n\t\t\treturn nullptr;\n\t}\n\telse if (nodes.size()>1)\n\t{\n\t\tthrow PineconeError(\"multiple copiers for a single type in a single namespace\", INTERNAL_ERROR);\n\t}\n\telse\n\t{\n\t\treturn nodes[0]->getAction();\n\t}\n\t*/\n}\n\nAction NamespaceData::getActionForTokenWithInput(Token token, Type left, Type right, bool dynamic, bool throwSourceError, Token tokenForError)\n{\n\tvector<Action> matches;\n\tvector<AstNodeBase*> nodes;\n\tbool foundNodes=false;\n\tAstNode tupleNode; // this is needed for memory management, so if a tuple node is needed it can be kept around until the function exits\n\t\n\tstring searchText = (token->getOp() ? token->getOp()->getText() : token->getText());\n\t\n\tgetNodes(nodes, searchText, true, dynamic, false);\n\t\n\tif (left->getType()==TypeBase::TUPLE && token->getType()==TokenData::IDENTIFIER)\n\t{\n\t\tauto match=left->getSubType(searchText);\n\t\t\n\t\tif (match.type)\n\t\t{\n\t\t\tif (right->isVoid())\n\t\t\t{\n\t\t\t\ttupleNode=AstActionWrapper::make(getElemFromTupleAction(left, searchText));\n\t\t\t\tnodes.push_back(&*tupleNode);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif (!nodes.empty())\n\t\tfoundNodes=true;\n\t\n\tnodesToMatchingActions(matches, nodes, left, right);\n\t\n\tif (!matches.empty())\n\t{\n\t\tif (matches.size() == 1)\n\t\t{\n\t\t\treturn matches[0];\n\t\t}\n\t\telse if (throwSourceError)\n\t\t{\n\t\t\tthrow PineconeError(\"multiple matching instances of '\"+token->getText()+\"' found\", SOURCE_ERROR, tokenForError);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn nullptr;\n\t\t}\n\t}\n\t\n\tnodes.clear();\n\tgetNodes(nodes, searchText, false, false, true);\n\t\n\tif (!nodes.empty())\n\t\tfoundNodes=true;\n\t\n\tfor (auto i: nodes)\n\t{\n\t\tAstNode instance=i->makeCopyWithSpecificTypes(left, right);\n\t\t\n\t\tif (instance)\n\t\t{\n\t\t\tmatches.push_back(instance->getAction());\n\t\t\tactions.add(token->getText(), move(instance));\n\t\t}\n\t}\n\t\n\tif (!matches.empty())\n\t{\n\t\tif (matches.size() == 1)\n\t\t{\n\t\t\treturn matches[0];\n\t\t}\n\t\telse if (throwSourceError)\n\t\t{\n\t\t\tthrow PineconeError(\"multiple whatev instances of '\"+token->getText()+\"' found\", SOURCE_ERROR, tokenForError);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn nullptr;\n\t\t}\n\t}\n\t\n\tif (!foundNodes && dynamic && token->getType()==TokenData::IDENTIFIER && left->isVoid() && right->isCreatable())\n\t{\n\t\treturn addVar(right, token->getText());\n\t}\n\t\n\tif (throwSourceError)\n\t{\n\t\tif (foundNodes)\n\t\t\tthrow PineconeError(\"correct overload of '\"+token->getText()+\"' not found for types \"+left->getString()+\" and \"+right->getString(), SOURCE_ERROR, tokenForError);\n\t\telse\n\t\t\tthrow PineconeError(\"'\"+token->getText()+\"' not found\", SOURCE_ERROR, tokenForError);\n\t}\n\telse\n\t{\n\t\treturn nullptr;\n\t}\n}\n\nvoid NamespaceData::getNodes(vector<AstNodeBase*>& out, string text, bool checkActions, bool checkDynamic, bool checkWhatev)\n{\n\tif (checkActions)\n\t{\n\t\tactions.get(text, out);\n\t}\n\t\n\tif (checkDynamic)\n\t{\n\t\tdynamicActions.get(text, out);\n\t}\n\t\n\tif (checkWhatev)\n\t{\n\t\twhatevActions.get(text, out);\n\t}\n\t\n\tif (parent)\n\t\tparent->getNodes(out, text, checkActions, checkDynamic, checkWhatev);\n}\n\nvoid NamespaceData::nodesToMatchingActions(vector<Action>& out, vector<AstNodeBase*>& nodes, Type leftInType, Type rightInType)\n{\n\tfor (auto i: nodes)\n\t{\n\t\tAction action=i->getAction();\n\t\t\n\t\tif (action->getInLeftType()->matches(leftInType) && action->getInRightType()->matches(rightInType))\n\t\t\tout.push_back(action);\n\t\t\n\t\t//Action converter=getConverter(action, leftInType, rightInType);\n\t}\n}\n\n"
  },
  {
    "path": "src/Parser.cpp",
    "content": "#include \"../h/Token.h\"\n#include \"../h/AstNode.h\"\n#include \"../h/Namespace.h\"\n#include \"../h/ErrorHandler.h\"\n#include \"../h/StackFrame.h\"\n#include \"../h/AllOperators.h\"\n#include \"../h/msclStringFuncs.h\"\n#include \"../h/AstNode.h\"\n\n#include <vector>\nusing std::vector;\n\n#include <iostream>\nusing std::cout;\nusing std::endl;\n\nusing std::min;\nusing std::max;\nusing std::pair;\n\nvoid lexString(shared_ptr<SourceFile> file, vector<Token>& tokens);\n\n//\tunless otherwise noted, these are what the perams for the following functions mean\n//\t\ttokens: the tokens to parse\n//\t\ttable: the table to use\n//\t\tleft: left most token to parse (inclusive)\n//\t\tright: right most token to parse (inclusive)\n//\t\treturns: (if type is AstNode) the action pointer for that section of the program\n\n//\tsplits a stream of tokens into a ListAstNode and calls parseExpression on each expression\nvoid parseTokenList(const vector<Token>& tokens, int left, int right, vector<AstNode>& nodes);\n\nint findExpressionSplit(const vector<Token>& tokens, int left, int right);\n\n//\trecursivly parses a single expression (no action lists)\nAstNode parseExpression(const vector<Token>& tokens, int left, int right);\n\n//\treturns the index of the closing brace that matches the given opening brace index, works with (), [], and {}\n//\t\ttokens: the token array to use\n//\t\tstart: the index of an open peren\n//\t\treturns: the index of the close peren that matches\nint skipBrace(const vector<Token>& tokens, int start);\n\nvoid parseSequence(const vector<Token>& tokens, int left, int right, Operator splitter, vector<AstNode>& out);\n\nAstNode parseOperator(const vector<Token>& tokens, int left, int right, int index);\n\n//AstNode parseLiteral(Token token);\n\nunique_ptr<AstType> parseType(const vector<Token>& tokens, int left, int right);\n//AstNode parseSingleTypeElement(const vector<Token>& tokens, int& i, int right, string& name, Type& type);\n//Type parseTypeToken(Token token);\n\nvoid importFile(vector<AstNode>& nodes, string path);\n\n//AstNode parseIdentifier(Token token, AstNode leftIn, AstNode rightIn);\n\n//void parseIdentifierConst(Token token, AstNode rightIn);\n\nAstNode astNodeFromTokens(const vector<Token>& tokens, int left, int right)\n{\n\tvector<AstNode> nodes;\n\t\n\tparseTokenList(tokens, left, right, nodes);\n\t\n\tif (nodes.size()==0)\n\t{\n\t\treturn AstVoid::make();\n\t}\n\telse if (nodes.size()==1)\n\t{\n\t\treturn move(nodes[0]);\n\t}\n\telse\n\t{\n\t\treturn AstList::make(nodes);\n\t}\n}\n\nint skipBrace(const vector<Token>& tokens, int start)\n{\n\tOperator open, close;\n\tint step;\n\t\n\tOperator op=tokens[start]->getOp();\n\t\n\tif (tokens[start]->getOp()==ops->openPeren)\n\t{\n\t\topen=ops->openPeren;\n\t\tclose=ops->closePeren;\n\t\tstep=1;\n\t}\n\telse if (tokens[start]->getOp()==ops->closePeren)\n\t{\n\t\topen=ops->closePeren;\n\t\tclose=ops->openPeren;\n\t\tstep=-1;\n\t}\n\telse if (tokens[start]->getOp()==ops->openSqBrac)\n\t{\n\t\topen=ops->openSqBrac;\n\t\tclose=ops->closeSqBrac;\n\t\tstep=1;\n\t}\n\telse if (tokens[start]->getOp()==ops->closeSqBrac)\n\t{\n\t\topen=ops->closeSqBrac;\n\t\tclose=ops->openSqBrac;\n\t\tstep=-1;\n\t}\n\telse if (tokens[start]->getOp()==ops->openCrBrac)\n\t{\n\t\topen=ops->openCrBrac;\n\t\tclose=ops->closeCrBrac;\n\t\tstep=1;\n\t}\n\telse if (tokens[start]->getOp()==ops->closeCrBrac)\n\t{\n\t\topen=ops->closeCrBrac;\n\t\tclose=ops->openCrBrac;\n\t\tstep=-1;\n\t}\n\telse\n\t{\n\t\tthrow PineconeError(FUNC + \" called with index that is not a valid brace\", INTERNAL_ERROR, tokens[start]);\n\t}\n\t\n\tint c=1;\n\tint i=start;\n\t\n\twhile(true)\n\t{\n\t\ti+=step;\n\t\t\n\t\tif (i>=int(tokens.size()))\n\t\t{\n\t\t\tthrow PineconeError(\"no matching brace\", SOURCE_ERROR, tokens[start]);\n\t\t}\n\t\t\n\t\tif (tokens[i]->getOp()==open)\n\t\t{\n\t\t\tc++;\n\t\t}\n\t\telse if (tokens[i]->getOp()==close)\n\t\t{\n\t\t\tc--;\n\t\t\t\n\t\t\tif (c<=0)\n\t\t\t{\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/*AstNode parseExpression(const vector<Token>& tokens, int left, int right)\n{\n\t//error.log(\"parsing expression: \"+stringFromTokens(tokens, left, right), JSYK);\n\t\n\tif (left>right)\n\t{\n\t\tthrow PineconeError(FUNC + \" sent left higher then right\", INTERNAL_ERROR, tokens[left]);\n\t}\n\telse if (left==right)\n\t{\n\t\treturn AstToken::make(tokens[left]);\n\t}\n\t\n\tvector<bool> isMinLeft(right-left+1);\n\tvector<bool> isMinRight(right-left+1);\n\t\n\tint lowest;\n\t\n\tlowest=10000; //an number bigger then any precedence\n\t\n\tfor (int i=left; i<=right; i++)\n\t{\n\t\tisMinLeft[i]=false;\n\t\tisMinRight[i]=false;\n\t}\n\t\n\tfor (int i=left; i<=right; i++)\n\t{\n\t\tOperator op=tokens[i]->getOp();\n\t\t\n\t\tif (op)\n\t\t{\n\t\t\tif (op==ops->openPeren || op==ops->openSqBrac || op==ops->openCrBrac)\n\t\t\t{\n\t\t\t\tint j=i;\n\t\t\t\ti=skipBrace(tokens, i);\n\t\t\t\t\n\t\t\t\tif (j==left && i==right)\n\t\t\t\t{\n\t\t\t\t\tif (op==ops->openPeren)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (left+1<right)\n\t\t\t\t\t\t\treturn parseTokenList(tokens, left+1, right-1);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\treturn AstVoid::make(); // a rare place where a astVoid may actually be intended by the programmer\n\t\t\t\t\t}\n\t\t\t\t\telse if (op==ops->openCrBrac)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn parseType(tokens, left+1, right-1);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow PineconeError(\"unknown bracket '\"+op->getText()+\"'\", INTERNAL_ERROR);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (op->getLeftPrece()<lowest)\n\t\t\t\t{\n\t\t\t\t\tisMinLeft[i]=true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tlowest=min(lowest, op->getRightPrece());\n\t\t}\n\t}\n\t\n\tlowest=10000; //an number bigger then any precedence\n\t\n\tfor (int i=right; i>=left; i--)\n\t{\n\t\tOperator op=tokens[i]->getOp();\n\t\t\n\t\tif (op)\n\t\t{\n\t\t\tif (op==ops->closePeren || op==ops->closeSqBrac || op==ops->closeCrBrac)\n\t\t\t{\n\t\t\t\ti=skipBrace(tokens, i);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (op->getRightPrece()<lowest)\n\t\t\t\t{\n\t\t\t\t\tisMinRight[i]=true;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tlowest=min(lowest, op->getLeftPrece());\n\t\t\t}\n\t\t}\n\t}\n\t\n\tfor (int i=left; i<=right; i++)\n\t{\n\t\tif (isMinLeft[i] && isMinRight[i])\n\t\t{\n\t\t\tAstNode leftNode=parseExpression(tokens, left, i-1);\n\t\t\tAstNode rightNode=parseExpression(tokens, i+1, right);\n\t\t\t\n\t\t\tif (tokens[i]->getOp()==ops->colon || tokens[i]->getOp()==ops->doubleColon)\n\t\t\t{\n\t\t\t\treturn AstExpression::make(AstVoid::make(), move(leftNode), move(rightNode));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn AstExpression::make(move(leftNode), AstToken::make(tokens[i]), move(rightNode));\n\t\t\t}\n\t\t}\n\t}\n\t\n\tthrow PineconeError(\"could not find where to split expression '\" + stringFromTokens(tokens, left, right) + \"'\", SOURCE_ERROR, tokens[left]);\n\t\t\n\t//error.log(\"range: \" + ([&]()->string{string out; for (int i=left; i<=right; i++) {out+=tokens[i]->getText()+\" \";} return out;})(), JSYK, tokens[left]);\n\t//error.log(\"isMin: \" + ([&]()->string{string out; for (auto i: isMin) {out+=\"\\n\"+to_string(i.first)+\", \"+to_string(i.second);} return out;})(), JSYK, tokens[left]);\n}\n*/\n\nint findExpressionSplit(const vector<Token>& tokens, int left, int right)\n{\n\tint minPrece=-1;\n\tint indexOfMin=-1;\n\t\n\tfor (int i=left; i<=right; i++)\n\t{\n\t\t//cout << \"looking at \" << tokens[i]->getText() << endl;\n\t\t/*if (tokens[i]->getOp())\n\t\t{\n\t\t\t//cout << \"precedence: \" << tokens[i]->getOp()->getPrecedence()\n\t\t}\n\t\t*/\n\t\t\n\t\tif (ops->isOpenBrac(tokens[i]->getOp()))\n\t\t{\n\t\t\tint j=skipBrace(tokens, i);\n\t\t\t\n\t\t\ti=j; // i is now the close brace, and after it is incremented it will be the token after that\n\t\t}\n\t\telse if (tokens[i]->getOp() && (minPrece<0 || tokens[i]->getOp()->getPrecedence()<minPrece))\n\t\t{\n\t\t\tminPrece=tokens[i]->getOp()->getPrecedence();\n\t\t\tindexOfMin=i;\n\t\t\t\n\t\t\t// this ensures that if the precedence is divisable by 2, the same precedence again will replace this one as the min\n\t\t\t// it is my way of making even precedences be right associative and odd ones be left associative\n\t\t\tif (minPrece%2)\n\t\t\t{\n\t\t\t\tminPrece++;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif (indexOfMin<0)\n\t{\n\t\tthrow PineconeError(FUNC+\" could not find operator to split expression\", INTERNAL_ERROR, tokens[left]);\n\t}\n\t\n\treturn indexOfMin;\n}\n\nAstNode parseExpression(const vector<Token>& tokens, int left, int right)\n{\n\t//error.log(FUNC+\" called on '\"+stringFromTokens(tokens, left, right)+\"'\", JSYK);\n\t\n\tif (left>right)\n\t{\n\t\tthrow PineconeError(FUNC + \" sent left higher then right\", INTERNAL_ERROR, tokens[left]);\n\t}\n\telse if (left==right)\n\t{\n\t\treturn AstToken::make(tokens[left]);\n\t}\n\t\n\tif (ops->isOpenBrac(tokens[left]->getOp()) && skipBrace(tokens, left)==right) // if the braces enclose this entire expression\n\t{\n\t\tif (tokens[left]->getOp()==ops->openPeren)\n\t\t{\n\t\t\treturn astNodeFromTokens(tokens, left+1, right-1);\n\t\t}\n\t\telse if (tokens[left]->getOp()==ops->openCrBrac)\n\t\t{\n\t\t\treturn parseType(tokens, left+1, right-1);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthrow PineconeError(\"unhandled brace '\"+tokens[left]->getOp()->getText()+\"'\", INTERNAL_ERROR, tokens[left]);\n\t\t}\n\t}\n\t\n\tint i=findExpressionSplit(tokens, left, right);\n\t\n\tOperator op=tokens[i]->getOp();\n\t\n\tif (op==ops->minus && i==left && i!=right)\n\t{\n\t\t//dont error\n\t}\n\telse if ((i==left)==op->takesLeftInput() || (i==right)==op->takesRightInput())\n\t{\n\t\tthrow PineconeError(\"improper use of '\"+op->getText()+\"' operator\", SOURCE_ERROR, tokens[i]);\n\t}\n\t\n\tif (op==ops->pipe)\n\t{\n\t\tthrow PineconeError(\"invalid use of '\"+op->getText()+\"'\", SOURCE_ERROR, tokens[i]);\n\t}\n\telse if (op==ops->ifOp || op==ops->loop || op==ops->rightArrow || op==ops->andOp || op==ops->orOp)\n\t{\n\t\tvector<AstNode> leftNodes;\n\t\tvector<AstNode> rightNodes;\n\t\t\n\t\tif (i>left)\n\t\t\tparseSequence(tokens, left, i-1, ops->pipe, leftNodes);\n\t\t\n\t\tif (i<right)\n\t\t\tparseSequence(tokens, i+1, right, ops->pipe, rightNodes);\n\t\t\n\t\treturn AstOpWithInput::make(leftNodes, tokens[i], rightNodes);\n\t}\n\telse if (op==ops->comma)\n\t{\n\t\tvector<AstNode> nodes;\n\t\t\n\t\tparseSequence(tokens, left, right, ops->comma, nodes);\n\t\t\n\t\treturn AstTuple::make(nodes);\n\t}\n\telse if (op==ops->doubleColon)\n\t{\n\t\tunique_ptr<AstToken> centerNode=nullptr;\n\t\tAstNode rightNode=nullptr;\n\t\t\n\t\tif (i==left+1 && tokens[i-1]->getType()==TokenData::IDENTIFIER)\n\t\t{\n\t\t\tcenterNode=AstToken::make(tokens[i-1]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthrow PineconeError(\"you can only use constant assignment on a single identifier\", SOURCE_ERROR, tokens[i]);\n\t\t}\n\t\t\n\t\tif (i<right)\n\t\t{\n\t\t\trightNode=parseExpression(tokens, i+1, right);\n\t\t}\n\t\telse\n\t\t{\n\t\t\trightNode=AstVoid::make();\n\t\t}\n\t\t\n\t\treturn AstConstExpression::make(move(centerNode), move(rightNode));\n\t}\n\telse if (op==ops->notEqual)\n\t{\n\t\tAstNode rightNode=i<right?parseExpression(tokens, i+1, right):AstVoid::make();\n\t\tAstNode leftNode=i>left?parseExpression(tokens, left, i-1):AstVoid::make();\n\t\tAstNode centerNode=AstToken::make(\n\t\t\tmakeToken(\n\t\t\t\tops->equal->getText(),\n\t\t\t\ttokens[i]->getFile(),\n\t\t\t\ttokens[i]->getLine(),\n\t\t\t\ttokens[i]->getCharPos()+1,\n\t\t\t\tTokenData::OPERATOR,\n\t\t\t\tops->equal\n\t\t\t)\n\t\t);\n\t\t\n\t\tAstNode notNode=AstToken::make(\n\t\t\tmakeToken(\n\t\t\t\tops->notOp->getText(),\n\t\t\t\ttokens[i]->getFile(),\n\t\t\t\ttokens[i]->getLine(),\n\t\t\t\ttokens[i]->getCharPos(),\n\t\t\t\tTokenData::OPERATOR,\n\t\t\t\tops->notOp\n\t\t\t)\n\t\t);\n\t\t\n\t\treturn AstExpression::make(\n\t\t\tAstVoid::make(),\n\t\t\tmove(notNode),\n\t\t\tAstExpression::make(\n\t\t\t\tmove(leftNode),\n\t\t\t\tmove(centerNode),\n\t\t\t\tmove(rightNode)\n\t\t\t)\n\t\t);\n\t}\n\telse if (op==ops->plusPlus || op==ops->minusMinus)\n\t{\n\t\tthrow PineconeError(\"++ and -- are not yet implemented\", SOURCE_ERROR, tokens[i]);\n\t\t\n\t\t//AstNode leftNode=parseExpression(tokens, left, i-1);\n\t\t\n\t\t//return AstExpression::make(AstVoid::make(), leftNode, AstExpression::make(leftNode, AstToken::make(Token)))\n\t}\n\telse if (op==ops->dot)\n\t{\n\t\treturn AstExpression::make\n\t\t(\n\t\t\ti>left ? parseExpression(tokens, left, i-1) : AstVoid::make(),\n\t\t\ti<right ? parseExpression(tokens, i+1, right) : AstVoid::make(),\n\t\t\tAstVoid::make()\n\t\t);\n\t}\n\telse if (op==ops->colon)\n\t{\n\t\tAstNode leftNode=AstVoid::make();\n\t\tAstNode centerNode=parseExpression(tokens, left, i-1);;\n\t\tAstNode rightNode=i<right?parseExpression(tokens, i+1, right):AstVoid::make();\n\t\t\n\t\t// make sure if it is an abc.xyz: ijk structure, it gets parsed as such, rather then (abc.xyz): ijk\n\t\t// we do this by parsing it the latter way (already done) and then detecting if we need to change it\n\t\tif (typeid(*centerNode)==typeid(AstExpression))\n\t\t{\n\t\t\tAstExpression * exprNode=(AstExpression*)&*centerNode;\n\t\t\t\n\t\t\tif (!exprNode->leftIn->isVoid() && !exprNode->center->isVoid() && exprNode->rightIn->isVoid())\n\t\t\t{\n\t\t\t\tleftNode=move(exprNode->leftIn);\n\t\t\t\tcenterNode=move(exprNode->center);\n\t\t\t}\n\t\t}\n\t\t\n\t\t// make a function body if needed, else make a normal expression\n\t\t\n\t\tif (\n\t\t\t(centerNode->isType() || centerNode->isFunctionWithOutput())\n\t\t\t&&\n\t\t\t(leftNode->isVoid() || leftNode->isType())\n\t\t\t&&\n\t\t\t!rightNode->isType()\n\t\t){\n\t\t\tif (leftNode->isVoid())\n\t\t\t\tleftNode=AstVoidType::make();\n\t\t\t\n\t\t\tAstNode funcRightIn;\n\t\t\tAstNode funcReturn;\n\t\t\t\n\t\t\tif (centerNode->isFunctionWithOutput())\n\t\t\t{\n\t\t\t\tfuncRightIn=move(((AstOpWithInput*)&*(centerNode))->leftIn[0]);\n\t\t\t\tfuncReturn=move(((AstOpWithInput*)&*(centerNode))->rightIn[0]);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfuncRightIn=move(centerNode);\n\t\t\t\tfuncReturn=AstVoidType::make();\n\t\t\t}\n\t\t\t\n\t\t\treturn AstFuncBody::make(move(leftNode), move(funcRightIn), move(funcReturn), move(rightNode));\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn AstExpression::make(move(leftNode), move(centerNode), move(rightNode));\n\t\t}\n\t}\n\telse\n\t{\n\t\treturn AstExpression::make\n\t\t(\n\t\t\ti>left ? parseExpression(tokens, left, i-1) : AstVoid::make(),\n\t\t\tAstToken::make(tokens[i]),\n\t\t\ti<right ? parseExpression(tokens, i+1, right) : AstVoid::make()\n\t\t);\n\t}\n}\n\nvoid parseTokenList(const vector<Token>& tokens, int left, int right, vector<AstNode>& nodes)\n{\n\tint start=left;\n\t\n\tfor (int i=left; i<=right; i++)\n\t{\n\t\tif (tokens[i]->getOp()==ops->import)\n\t\t{\n\t\t\tif (i==right || tokens[i+1]->getType()!=TokenData::STRING_LITERAL)\n\t\t\t{\n\t\t\t\tthrow PineconeError(\"'\"+ops->import->getText()+\"' must be followed by a string literal\", SOURCE_ERROR, tokens[i]);\n\t\t\t}\n\t\t\t\n\t\t\tstring path=tokens[i+1]->getText();\n\t\t\t\n\t\t\t//this nonesens is required because my lexer is shit and includes the first quote but not the last one\n\t\t\t//instead of hardcoding that in, I figured I'd make it flexable so I don't break everthing when I fix the lexer\n\t\t\t\n\t\t\twhile (path.size()>0 && path[0]=='\"')\n\t\t\t\tpath=path.substr(1, string::npos);\n\t\t\t\n\t\t\twhile (path.size()>0 && path[path.size()-1]=='\"')\n\t\t\t\tpath=path.substr(0, path.size()-1);\n\t\t\t\n\t\t\tpath=tokens[i]->getFile()->getDirPath()+\"/\"+path;\n\t\t\t\n\t\t\ttry\n\t\t\t{\n\t\t\t\timportFile(nodes, path);\n\t\t\t}\n\t\t\tcatch (PineconeError err)\n\t\t\t{\n\t\t\t\terr.log();\n\t\t\t}\n\t\t\t\n\t\t\t\n\t\t\ti+=2;\n\t\t\tstart=i;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (ops->isOpenBrac(tokens[i]->getOp()))\n\t\t\t{\n\t\t\t\ti=skipBrace(tokens, i);\n\t\t\t}\n\t\t\t\n\t\t\tbool tokenTakesRightInput=(tokens[i]->getOp() && tokens[i]->getOp()->takesRightInput());\n\t\t\tint next=i+1;\n\t\t\tbool nextTokenTakesLeftInput=(next<=right && tokens[next]->getOp() && tokens[next]->getOp()->takesLeftInput());\n\t\t\t\n\t\t\tif (i==right || (!tokenTakesRightInput && !nextTokenTakesLeftInput))\n\t\t\t{\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tAstNode node=parseExpression(tokens, start, i);\n\t\t\t\t\tnodes.push_back(move(node));\n\t\t\t\t}\n\t\t\t\tcatch (PineconeError err)\n\t\t\t\t{\n\t\t\t\t\terr.log();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tstart=next;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/*AstNode parseTokenList(const vector<Token>& tokens, int left, int right)\n{\n\tvector<AstNode> nodes;\n\t\n\twhile (left<=right)\n\t{\n\t\tint i=left;\n\t\t\n\t\twhile(true)\n\t\t{\n\t\t\tauto op=tokens[i]->getOp();\n\t\t\t\n\t\t\tif (op==ops->openPeren || op==ops->openSqBrac || op==ops->openCrBrac)\n\t\t\t\ti=skipBrace(tokens, i);\n\t\t\t\n\t\t\tif (i>=right) // at the end\n\t\t\t{\n\t\t\t\tif (nodes.empty())\n\t\t\t\t{\n\t\t\t\t\treturn parseExpression(tokens, left, right);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ttry\n\t\t\t\t\t{\n\t\t\t\t\t\tnodes.push_back(parseExpression(tokens, left, right));\n\t\t\t\t\t}\n\t\t\t\t\tcatch (PineconeError err)\n\t\t\t\t\t{\n\t\t\t\t\t\terr.log();\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (!tokens[i]->getOp() && !tokens[i+1]->getOp())// if the left can't absorb the right and the right cant absorbe the left\n\t\t\t{\n\t\t\t\tnodes.push_back(parseExpression(tokens, left, i));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\ti++;\n\t\t}\n\t\t\n\t\tleft=i+1;\n\t}\n\t\n\treturn AstList::make(nodes);\n}*/\n\nvoid parseSequence(const vector<Token>& tokens, int left, int right, Operator splitter, vector<AstNode>& out)\n{\n\tint start=left;\n\t\n\tfor (int i=left; i<=right; i++)\n\t{\n\t\tif (ops->isOpenBrac(tokens[i]->getOp()))\n\t\t{\n\t\t\ti=skipBrace(tokens, i);\n\t\t}\n\t\telse if (tokens[i]->getOp()==splitter)\n\t\t{\n\t\t\tif (start<=i-1)\n\t\t\t\tout.push_back(parseExpression(tokens, start, i-1));\n\t\t\tstart=i+1;\n\t\t}\n\t\telse if (tokens[i]->getOp() && tokens[i]->getOp()->getPrecedence()==splitter->getPrecedence())\n\t\t{\n\t\t\tbreak;\n\t\t}\n\t\telse if (tokens[i]->getOp() && tokens[i]->getOp()->getPrecedence()<splitter->getPrecedence())\n\t\t{\n\t\t\tout.clear();\n\t\t\tout.push_back(parseExpression(tokens, left, right));\n\t\t\treturn;\n\t\t}\n\t}\n\t\n\tif (start<=right)\n\t\tout.push_back(parseExpression(tokens, start, right));\n}\n\nunique_ptr<AstType> parseType(const vector<Token>& tokens, int left, int right)\n{\n\tvector<AstTupleType::NamedType> types;\n\t\n\twhile (left<=right)\n\t{\n\t\t//\tskip commas\n\t\twhile (left<=right && tokens[left]->getOp()==ops->comma)\n\t\t{\n\t\t\tleft++;\n\t\t}\n\t\t\n\t\t//\tif this is a named subtype\n\t\tif (left+2<=right && tokens[left+1]->getOp()==ops->colon)\n\t\t{\n\t\t\tif (tokens[left]->getType()!=TokenData::IDENTIFIER)\n\t\t\t{\n\t\t\t\tthrow PineconeError(\"identifier must be to the left of ':' in type\", SOURCE_ERROR, tokens[left]);\n\t\t\t}\n\t\t\t\n\t\t\tToken name=tokens[left];\n\t\t\tunique_ptr<AstType> type;\n\t\t\t\n\t\t\tif (tokens[left+2]->getType()==TokenData::IDENTIFIER)\n\t\t\t{\n\t\t\t\ttype=AstTokenType::make(tokens[left+2]);\n\t\t\t\tleft+=3;\n\t\t\t}\n\t\t\telse if (tokens[left+2]->getOp()==ops->openCrBrac)\n\t\t\t{\n\t\t\t\tint j=skipBrace(tokens, left+2);\n\t\t\t\t\n\t\t\t\tif (j>right)\n\t\t\t\t{\n\t\t\t\t\tthrow PineconeError(FUNC+\" skipping brance went outside of range\", INTERNAL_ERROR, tokens[left+1]);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\ttype=parseType(tokens, left+2+1, j-1);\n\t\t\t\tleft=j+1;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthrow PineconeError(\"invalid thingy '\"+tokens[left+2]->getText()+\"' in type\", SOURCE_ERROR, tokens[left+2]);\n\t\t\t}\n\t\t\t\n\t\t\ttypes.push_back(AstTupleType::NamedType{name, move(type)});\n\t\t}\n\t\telse //\tthis is an unnamed subtype\n\t\t{\n\t\t\ttypes.push_back(AstTupleType::NamedType{nullptr, AstTokenType::make(tokens[left])});\n\t\t\tleft+=1;\n\t\t}\n\t}\n\t\n\tif (types.size()==0)\n\t\treturn AstVoidType::make();\n\telse if (types.size()==1 && !types[0].name)\n\t\treturn move(types[0].type);\n\telse\n\t\treturn AstTupleType::make(types);\n}\n\n/* Type parseTypeToken(Token token, Namespace table)\n{\n\tif (token->getType()==TokenData::IDENTIFIER)\n\t{\n\t\tType type=table->getType(token->getText());\n\t\t\n\t\tif (type)\n\t\t{\n\t\t\treturn type;\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror.log(\"could not find type \"+token->getDescription(), SOURCE_ERROR, token);\n\t\t\treturn Void;\n\t\t}\n\t}\n\telse\n\t{\n\t\terror.log(FUNC+\" called with non identifier token \"+token->getText(), INTERNAL_ERROR, token);\n\t\treturn Void;\n\t}\n}\n*/\n\nvoid importFile(vector<AstNode>& nodes, string path)\n{\n\tauto file=shared_ptr<SourceFile>(new SourceFile(path, false));\n\t\n\tif (file->getContents().empty())\n\t{\n\t\tthrow PineconeError(\"file '\"+path+\"' failed to open or was empty\", SOURCE_ERROR);\n\t}\n\t\n\tvector<Token> tokens;\n\t\n\tlexString(file, tokens);\n\t\n\tparseTokenList(tokens, 0, tokens.size()-1, nodes);\n}\n\n"
  },
  {
    "path": "src/PineconeProgram.cpp",
    "content": "#include \"../h/PineconeProgram.h\"\n#include \"../h/ErrorHandler.h\"\n#include \"../h/Operator.h\"\n#include \"../h/AllOperators.h\"\n#include \"../h/CppProgram.h\"\n\nvoid populatePineconeStdLib();\nvoid lexString(shared_ptr<SourceFile> file, vector<Token>& tokens);\nAction parseFunction(const vector<Token>& tokens, int left, int right, Type leftInType, Type rightInType);\n\nextern Namespace globalNamespace;\n\nPineconeProgram::PineconeProgram()\n{\n\t\n}\n\nvoid PineconeProgram::cleanUp()\n{\n\t\n}\n\nvoid PineconeProgram::resolveProgram(string inFilename, bool printOutput)\n{\n\tAllOperators::init();\n\tpopulatePineconeStdLib();\n\t\n\t//initialProgramPopulation();\n\t\n\t//globalFrame.resolve(printOutput);\n\t\n\tif (!error.getIfErrorLogged())\n\t{\n\t\ttry\n\t\t{\n\t\t\tfile=shared_ptr<SourceFile>(new SourceFile(inFilename, printOutput));\n\t\t\t\n\t\t\tif (printOutput)\n\t\t\t{\n\t\t\t\tcout << endl << endl << file->getBoxedString() << endl;\n\t\t\t}\n\t\t}\n\t\tcatch (PineconeError err)\n\t\t{\n\t\t\terr.log();\n\t\t}\n\t}\n\t\n\tif (!error.getIfErrorLogged())\n\t{\n\t\ttry\n\t\t{\n\t\t\tlexString(file, tokens);\n\t\t}\n\t\tcatch (PineconeError err)\n\t\t{\n\t\t\terr.log();\n\t\t\tastRoot=AstVoid::make();\n\t\t}\n\t\t\n\t\t/*\n\t\tif (printOutput)\n\t\t{\n\t\t\tcout << endl << tableStringFromTokens(tokens, \"lexer output\") << endl;\n\t\t}\n\t\t*/\n\t}\n\t\n\t//astRoot=parseFunction(tokens, 0, tokens.size()-1, Void, Void);\n\t\n\tif (!error.getIfErrorLogged())\n\t{\n\t\ttry\n\t\t{\n\t\t\tastRoot=astNodeFromTokens(tokens, 0, tokens.size()-1);\n\t\t}\n\t\tcatch (PineconeError err)\n\t\t{\n\t\t\terr.log();\n\t\t\tastRoot=AstVoid::make();\n\t\t}\n\t\t\n\t\tif (printOutput)\n\t\t{\n\t\t\tcout << \" ╭──────────────────────╮\" << endl;\n\t\t\tcout << \" │ abstract syntax tree │\" << endl;\n\t\t\tcout << \" ╰──────────────────────╯\" << endl;\n\t\t\tcout << astRoot->getString() << endl;\n\t\t\t//cout << endl << putStringInBox(astRoot->getString(), \"abstract syntax tree\") << endl;\n\t\t\t//cout << endl << str::getBoxedString(astRoot->getString(), \"abstract syntax tree\") << endl;\n\t\t}\n\t}\n\t\n\tif (!error.getIfErrorLogged())\n\t{\n\t\ttry\n\t\t{\n\t\t\tastRoot->setInput(globalNamespace, true, Void, Void);\n\t\t}\n\t\tcatch (PineconeError err)\n\t\t{\n\t\t\terr.log();\n\t\t\tastRoot=AstVoid::make();\n\t\t}\n\t\t\n\t\ttry\n\t\t{\n\t\t\tactionRoot=astRoot->getAction();\n\t\t\t\n\t\t\tif (printOutput)\n\t\t\t{\n\t\t\t\tcout << \" ╭─────────────╮\" << endl;\n\t\t\t\tcout << \" │ action tree │\" << endl;\n\t\t\t\tcout << \" ╰─────────────╯\" << endl;\n\t\t\t\tcout << actionRoot->getDescription() << endl;\n\t\t\t\t//cout << endl << str::getBoxedString(actionRoot->getDescription(), \"action tree\") << endl;\n\t\t\t}\n\t\t}\n\t\tcatch (PineconeError err)\n\t\t{\n\t\t\terr.log();\n\t\t}\n\t}\n\t\n\t/*if (printOutput)\n\t{\n\t\tcout << endl << \"C source code:\\n\" << astRoot->getCSource() << endl;\n\t}*/\n\t\n}\n\nstring PineconeProgram::getCpp()\n{\n\ttry\n\t{\n\t\tCppProgram outProg;\n\t\tactionRoot->addToProg(voidAction, voidAction, &outProg);\n\t\treturn outProg.getCppCode();\n\t}\n \tcatch (PineconeError err)\n\t{\n\t\terr.log();\n\t\treturn \"/* no program due to transpiling error */\";\n\t}\n}\n\nvoid PineconeProgram::execute()\n{\n\ttry\n\t{\n\t\tstackPtr=globalFramePtr=malloc(globalNamespace->getStackFrame()->getSize());\n\t\tfree(actionRoot->execute(nullptr, nullptr));\n\t\tfree(globalFramePtr);\n\t\tstackPtr=globalFramePtr=nullptr;\n\t}\n\tcatch (PineconeError err)\n\t{\n\t\terr.log();\n\t\tcout << endl << \">>>>>>    program aborted due to error    <<<<<<\" << endl;\n\t}\n}\n\n"
  },
  {
    "path": "src/PineconeStdLib.cpp",
    "content": "#include \"../h/PineconeProgram.h\"\n#include \"../h/AllOperators.h\"\n#include \"../h/StackFrame.h\"\n#include \"../h/Namespace.h\"\n#include \"../h/CppProgram.h\"\n#include \"../h/utils/stringUtils.h\"\n#include \"../h/Type.h\"\n\n#define CONCAT(a,b) a##_##b\n#define GET_TYPES_Tuple(t0, t1) t0, t1\n\n#define assert if (\n#define otherwise ) {} else\n\n#define getPncnType(typeIn) CONCAT(PNCN, typeIn)\n#define getCppType(typeIn) CONCAT(CPP, typeIn)\n\n#define CPP_Dub double\n#define CPP_Byte unsigned char\n#define CPP_Int int\n#define CPP_Bool bool\n#define CPP_Void char\n\n#define PNCN_String String\n#define PNCN_Dub Dub\n#define PNCN_Int Int\n#define PNCN_Byte Byte\n#define PNCN_Bool Bool\n#define PNCN_Void Void\n//#define PNCN_Tuple(t1, t2) Type(new TypeData(vector<Type>({PNCN##_##t1, PNCN##_##t2}), \"\"))\n#define PNCN_Tuple(t1, t2) makeTuple(vector<NamedType>({{\"a\", t1}, {\"b\", t2}}), true)\n\n#define LAMBDA_HEADER [](void* leftIn, void* rightIn)->void*\n#define ADD_CPP_HEADER [](Action left, Action right, CppProgram* prog)->void\n\n#define retrn out=\n\n#define GET_PTR_VAL(typeIn, varInName) =*((getCppType(typeIn)*)(varInName))\n\n#define DO_INSTANTIATE(typeIn, varOutName, valIn) getCppType(typeIn) varOutName valIn;\n#define DONT_INSTANTIATE(typeIn, varOutName, valIn) ;\n#define INSTANTIATE_CPP_TUPLE(t0, t1, varOutName, valIn)\\\n\tDO_INSTANTIATE(t0, CONCAT(varOutName, 0), valIn)\\\n\tDO_INSTANTIATE(t1, CONCAT(varOutName, 1), ((char *)valIn)+sizeof(getCppType(t0)))\\\n\n#define DO_RETURN_VAL(typeIn, varName) void* outPtr=malloc(getPncnType(typeIn)->getSize()); memcpy(outPtr, &varName, getPncnType(typeIn)->getSize()); return outPtr;\n#define DONT_RETURN_VAL(typeIn, varName) return nullptr;\n\n#define INSTANTIATE_String DO_INSTANTIATE\n#define INSTANTIATE_Dub DO_INSTANTIATE\n#define INSTANTIATE_Int DO_INSTANTIATE\n#define INSTANTIATE_Byte DO_INSTANTIATE\n#define INSTANTIATE_Bool DO_INSTANTIATE\n#define INSTANTIATE_Void DONT_INSTANTIATE\n#define INSTANTIATE_Tuple__(typeIn, varOutName, valIn) INSTANTIATE_CPP_TUPLE(typeIn, varOutName, valIn)\n#define INSTANTIATE_Tuple_(typeIn, varOutName, valIn) INSTANTIATE_Tuple__(GET_TYPES##_##typeIn, varOutName, valIn)\n#define INSTANTIATE_Tuple(t1, t2) INSTANTIATE_Tuple_\n\n#define RETURN_Dub DO_RETURN_VAL\n#define RETURN_Int DO_RETURN_VAL\n#define RETURN_Byte DO_RETURN_VAL\n#define RETURN_Bool DO_RETURN_VAL\n#define RETURN_Void DONT_RETURN_VAL\n\n#define func(nameText, leftType, rightType, returnType, lambdaBody, cpp)\t\t\t\t\t\\\naddAction(nameText, getPncnType(leftType), getPncnType(rightType), getPncnType(returnType), LAMBDA_HEADER\\\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tINSTANTIATE##_##leftType(leftType, left, GET_PTR_VAL(leftType, leftIn))\t\t\t\t\t\\\n\tINSTANTIATE##_##rightType(rightType, right, GET_PTR_VAL(rightType, rightIn))\t\t\t\\\n\tINSTANTIATE##_##returnType(returnType, out, ;)\t\t\t\t\t\t\t\t\t\t\t\\\n\tlambdaBody;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tCONCAT(RETURN, returnType)(returnType, out)\t\t\t\t\t\t\t\t\t\t\t\t\\\n},\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\ncpp\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\nAction voidAction;\n\n//shared_ptr<StackFrame> stdLibStackFrame;\nNamespace globalNamespace;\nNamespace table; // is set to equal globalNamespace, not sure why I have both. I think just because table is shorter (so its used in this file) and globalNamespace is clearer (so its used everywhere else)\n\nstring getText(Operator op) {return op->getText();}\nstring getText(string in) {return in;}\n\nvoid addConst(void* data, Type type, string name)\n{\n\tglobalNamespace->addNode(AstActionWrapper::make(constGetAction(data, type, name, globalNamespace)), name);\n}\n\ntemplate<typename T>\nvoid addAction(T id, Type leftType, Type rightType, Type returnType, function<void*(void*, void*)> lambda, function<void(Action inLeft, Action inRight, CppProgram* prog)> addCppToProg)\n{\n\tglobalNamespace->addNode(AstActionWrapper::make(lambdaAction(leftType, rightType, returnType, lambda, addCppToProg, getText(id))), getText(id));\n}\n\nvoid addType(Type type, string id)\n{\n\tauto node=AstTypeType::make(type);\n\tnode->setInput(globalNamespace, false, Void, Void);\n\tglobalNamespace->addNode(move(node), id);\n}\n\nfunction<void(Action inLeft, Action inRight, CppProgram* prog)> stringToLambda(string cppCode)\n{\n\tif (cppCode.empty())\n\t{\n\t\treturn nullptr;\n\t}\n\t\n\treturn [=](Action inLeft, Action inRight, CppProgram* prog)\n\t{\n\t\tint start=0;\n\t\tint i;\n\t\t\n\t\tdo\n\t\t{\n\t\t\ti=searchInString(cppCode, \"$\", start);\n\t\t\t\n\t\t\tif (i<0)\n\t\t\t{\n\t\t\t\tprog->code(cppCode.substr(start, cppCode.size()-start));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tprog->code(cppCode.substr(start, i-start));\n\t\t\t\t\n\t\t\t\tif (substringMatches(cppCode, i, \"$.\"))\n\t\t\t\t{\n\t\t\t\t\tprog->pushExpr();\n\t\t\t\t\t\tinLeft->addToProg(prog);\n\t\t\t\t\t\tstart=i+string(\"$.\").size();\n\t\t\t\t\tprog->popExpr();\n\t\t\t\t}\n\t\t\t\telse if (substringMatches(cppCode, i, \"$:\"))\n\t\t\t\t{\n\t\t\t\t\tprog->pushExpr();\n\t\t\t\t\t\tinRight->addToProg(prog);\n\t\t\t\t\t\tstart=i+string(\"$:\").size();\n\t\t\t\t\tprog->popExpr();\n\t\t\t\t}\n\t\t\t\telse if (substringMatches(cppCode, i, \"$$\"))\n\t\t\t\t{\n\t\t\t\t\tprog->code(\"$\");\n\t\t\t\t\tstart=i+string(\"$$\").size();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tthrow PineconeError(\"invalid '$' escape in C++ code: \"+cppCode, INTERNAL_ERROR);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t} while (i>=0);\n\t\t\n\t\t//if (prog->getExprLevel()==0)\n\t\t//\tprog->endln();\n\t};\n}\n\nvoid addAction(string text, Type leftType, Type rightType, Type returnType, function<void*(void*, void*)> lambda, string cpp)\n{\n\taddAction(text, leftType, rightType, returnType, lambda, stringToLambda(cpp));\n}\n\nvoid addAction(Operator op, Type leftType, Type rightType, Type returnType, function<void*(void*, void*)> lambda, string cpp)\n{\n\taddAction(op, leftType, rightType, returnType, lambda, stringToLambda(cpp));\n}\n\nType IntArray=nullptr;\nType Array=nullptr;\n\ntemplate<typename T>\ninline T getValFromTuple(void* data, Type type, string name)\n{\n\twhile (type->getType()==TypeBase::PTR)\n\t{\n\t\ttype=type->getSubType();\n\t\tdata=*(void**)data;\n\t}\n\t\n\tOffsetAndType a=type->getSubType(name);\n\t\n\tif (!a.type)\n\t\tthrow PineconeError(\"tried to get invalid property '\"+name+\"' from type \"+type->getString(), INTERNAL_ERROR);\n\t\t\n\treturn *((T*)((char*)data+a.offset));\n}\n/*\ntemplate<typename T>\ninline T getValFromTuple(void* data, Type type, int index)\n{\n\tif (index<0 || index>=type->getAllSubTypes()->size())\n\t\tthrow PineconeError(\"tried to get invalid property #\"+to_string(index)+\" from tuple \"+type->getString(), INTERNAL_ERROR);\n\t\t\n\tint offset=0;\n\t\n\tfor (int i=0; i<index; i++)\n\t{\n\t\toffset+=(*type->getAllSubTypes())[i]->getSize();\n\t}\n\t\n\treturn *((T*)((char*)data+offset));\n}\n*/\n\ntemplate<typename T>\ninline void setValInTuple(void* data, Type type, string name, T val)\n{\n\twhile (type->getType()==TypeBase::PTR)\n\t{\n\t\ttype=type->getSubType();\n\t\tdata=*(void**)data;\n\t}\n\t\t\n\tOffsetAndType a=type->getSubType(name);\n\t\n\tif (!a.type)\n\t\tthrow PineconeError(\"tried to set invalid property '\"+name+\"' from type \"+type->getString(), INTERNAL_ERROR);\n\t\n\t*((T*)((char*)data+a.offset))=val;\n}\n\ninline string pncnStr2CppStr(void* obj)\n{\n\tint len=getValFromTuple<int>(obj, String, \"_size\");\n\tchar * data=(char*)malloc((len+1)*sizeof(char));\n\tmemcpy(data, getValFromTuple<char*>(obj, String, \"_data\"), len*sizeof(char));\n\tdata[len]=0;\n\tstring out(data);\n\treturn out;\n}\n\ninline void* cppStr2PncnStr(string cpp)\n{\n\tvoid * obj=malloc(String->getSize());\n\tchar * strData=(char*)malloc(cpp.size()*sizeof(char));\n\tmemcpy(strData, cpp.c_str(), cpp.size()*sizeof(char));\n\t\n\t*((int*)((char*)obj+String->getSubType(\"_size\").offset))=cpp.size();\n\t*((char**)((char*)obj+String->getSubType(\"_data\").offset))=strData;\n\t\n\treturn obj;\n}\n\n\n/// add C++ funcs to program\n\nvoid addToProgPnStr(CppProgram * prog)\n{\n\tif (!prog->hasFunc(\"$pnStr\"))\n\t{\n\t\tstring strType=prog->getTypeCode(String);\n\t\t\n\t\tprog->addFunc(\"$pnStr\", {{\"const char *\", \"in\"}}, strType,\n\t\t\t\"int size = 0;\\n\"\n\t\t\t\"while (in[size]) size++;\\n\"\n\t\t\t//\"unsigned char * data = (unsigned char *)malloc(size);\\n\"\n\t\t\t//\"memcpy(data, in, s ize);\\n\"\n\t\t\t//\"return \"+strType+\"(size, data);\\n\"\n\t\t\t\"return \"+strType+\"(size, (unsigned char*)in);\\n\"\n\t\t);\n\t}\n}\n\nvoid addToProgCStr(CppProgram * prog)\n{\n\tif (!prog->hasFunc(\"$cStr\"))\n\t{\n\t\tif (prog->hasFunc(\"$cStr\"))\n\t\t\treturn;\n\t\t\n\t\tstring strType=prog->getTypeCode(String);\n\t\t\n\t\tprog->addFunc(\"$cStr\", {{strType, \"in\"}}, \"char *\",\n\t\t\t\"char * out = (char *)malloc(in._size+1);\\n\"\n\t\t\t\"memcpy(out, in._data, in._size);\\n\"\n\t\t\t\"out[in._size] = 0;\\n\"\n\t\t\t\"return out;\\n\"\n\t\t);\n\t}\n}\n\nvoid addToProgSubStr(CppProgram * prog)\n{\n\tif (!prog->hasFunc(\"$subStr\"))\n\t{\n\t\tstring strType=prog->getTypeCode(String);\n\t\t\n\t\tprog->addFunc(\"$subStr\", {{strType, \"in\"}, {\"int\", \"a\"}, {\"int\", \"b\"}}, strType,\n\t\t\t\"int size = b - a;\\n\"\n\t\t\t\"unsigned char * data = (unsigned char *)malloc(size);\\n\"\n\t\t\t\"memcpy(data, in._data + a, size);\\n\"\n\t\t\t\"return \"+strType+\"(size, data);\\n\"\n\t\t);\n\t}\n}\n\nvoid addToProgIntToStr(CppProgram * prog)\n{\n\tif (!prog->hasFunc(\"$intToStr\"))\n\t{\n\t\tstring strType=prog->getTypeCode(String);\n\t\t\n\t\tprog->addFunc(\"$intToStr\", {{\"int\", \"in\"}}, prog->getTypeCode(String),\n\t\t\t\"bool neg = in < 0;\\n\"\n\t\t\t\"if (neg) in *= -1;\\n\"\n\t\t\t\"int val = in;\\n\"\n\t\t\t\"int size = 0;\\n\"\n\t\t\t\"while (val)\\n\"\n\t\t\t\"{\\n\"\n\t\t\t\"\tsize++;\\n\"\n\t\t\t\"\tval /= 10;\\n\"\n\t\t\t\"}\\n\"\n\t\t\t\"if (size == 0)\\n\\tsize = 1;\\n\"\n\t\t\t\"if (neg)\\n\\tsize++;\\n\"\n\t\t\t\"unsigned char * data = (unsigned char *)malloc(size);\\n\"\n\t\t\t\"val = in;\\n\"\n\t\t\t\"for (int i = 0; i<(neg ? size-1 : size); i++)\\n\"\n\t\t\t\"{\\n\"\n\t\t\t\"\tdata[size-i-1] = (val % 10) + '0';\\n\"\n\t\t\t\"\tval /= 10;\\n\"\n\t\t\t\"}\\n\"\n\t\t\t\"if (neg)\\n\\tdata[0] = '-';\\n\"\n\t\t\t\"return \"+strType+\"(size, data);\\n\"\n\t\t);\n\t}\n}\n\nvoid addToProgStrToInt(CppProgram * prog)\n{\n\tif (!prog->hasFunc(\"$strToInt\"))\n\t{\n\t\tstring strType=prog->getTypeCode(String);\n\t\t\n\t\tprog->addFunc(\"$strToInt\", {{strType, \"in\"}}, \"int\",\n\t\t\t\"int out = 0;\\n\"\n\t\t\t\"for (int i = 0; i < in._size; i++)\\n\"\n\t\t\t\"{\\n\"\n\t\t\t\"\tif (in._data[i] >= '0' && in._data[i] <= '9')\\n\"\n\t\t\t\"\t{\\n\"\n\t\t\t\"\t\tout = out * 10 + in._data[i] - '0';\\n\"\n\t\t\t\"\t}\\n\"\n\t\t\t\"\telse if (in._data[i] == '.')\\n\"\n\t\t\t\"\t\tbreak;\\n\"\n\t\t\t\"}\\n\"\n\t\t\t\"if (in._size > 0 && in._data[0] == '-')\\n\"\n\t\t\t\"\tout *= -1;\\n\"\n\t\t\t\"return out;\\n\"\n\t\t);\n\t}\n}\n\nvoid addToProgStrToDub(CppProgram * prog)\n{\n\tif (!prog->hasFunc(\"$strToDub\"))\n\t{\n\t\tstring strType=prog->getTypeCode(String);\n\t\t\n\t\tprog->addFunc(\"$strToDub\", {{strType, \"in\"}}, \"double\",\n\t\t\t\"double out = 0;\\n\"\n\t\t\t\"int divider = 1;\\n\"\n\t\t\t\"for (int i = 0; i < in._size; i++)\\n\"\n\t\t\t\"{\\n\"\n\t\t\t\"\tif (divider == 1)\\n\"\n\t\t\t\"\t{\\n\"\n\t\t\t\"\t\tif (in._data[i] >= '0' && in._data[i] <= '9')\\n\"\n\t\t\t\"\t\t\tout = out * 10 + in._data[i] - '0';\\n\"\n\t\t\t\"\t\telse if (in._data[i] == '.')\\n\"\n\t\t\t\"\t\t\tdivider = 10;\\n\"\n\t\t\t\"\t}\\n\"\n\t\t\t\"\telse\\n\"\n\t\t\t\"\t{\\n\"\n\t\t\t\"\t\tif (in._data[i] >= '0' && in._data[i] <= '9')\\n\"\n\t\t\t\"\t\t{\\n\"\n\t\t\t\"\t\t\tout += ((double)(in._data[i] - '0')) / (double)divider;\\n\"\n\t\t\t\"\t\t\tdivider *= 10;\\n\"\n\t\t\t\"\t\t}\\n\"\n\t\t\t\"\t}\\n\"\n\t\t\t\"}\\n\"\n\t\t\t\"if (in._size > 0 && in._data[0] == '-')\\n\"\n\t\t\t\"\tout *= -1;\\n\"\n\t\t\t\"return out;\\n\"\n\t\t);\n\t}\n}\n\nvoid addToProgConcatStr(CppProgram * prog)\n{\n\tif (!prog->hasFunc(\"$concatStr\"))\n\t{\n\t\tstring strType=prog->getTypeCode(String);\n\t\t\n\t\tprog->addFunc(\"$concatStr\", {{strType, \"a\"}, {strType, \"b\"}}, strType,\n\t\t\t\"int newSize = a._size + b._size;\\n\"\n\t\t\t\"unsigned char * newData = (unsigned char *)malloc(newSize);\\n\"\n\t\t\t\"memcpy(newData, a._data, a._size);\\n\"\n\t\t\t\"memcpy(newData + a._size, b._data, b._size);\\n\"\n\t\t\t\"return \"+strType+\"(newSize, newData);\\n\"\n\t\t);\n\t}\n}\n\nvoid addToProgDoubleToStr(CppProgram * prog)\n{\n\tif (!prog->hasFunc(\"$doubleToStr\"))\n\t{\n\t\taddToProgIntToStr(prog);\n\t\taddToProgConcatStr(prog);\n\t\taddToProgPnStr(prog);\n\t\t\n\t\tstring intToStr=prog->pnToCpp(\"$intToStr\");\n\t\tstring concat=prog->pnToCpp(\"$concatStr\");\n\t\tstring pnStr=prog->pnToCpp(\"$pnStr\");\n\t\t\n\t\tprog->addFunc(\"$doubleToStr\", {{\"double\", \"in\"}}, prog->getTypeCode(String),\n\t\t\t\n\t\t\t\"long long b = (in - (long long)in) * 10000000000 * (in>=0 ? 1 : -1);\\n\"\n\t\t\t\"if (b % 10 == 9)\\n\\tb += 1;\\n\"\n\t\t\t\"while (b>0 && !(b % 10))\\n\\tb /= 10;\\n\"\n\t\t\t\"return \"+concat+\"(\"+concat+\"(\"+intToStr+\"((int)in), \"+pnStr+\"(\\\".\\\")), \"+intToStr+\"(b));\\n\"\n\t\t);\n\t}\n}\n\nvoid addToProgAsciiToStr(CppProgram * prog)\n{\n\tif (!prog->hasFunc(\"$asciiToStr\"))\n\t{\n\t\tstring strType=prog->getTypeCode(String);\n\t\t\n\t\tprog->addFunc(\"$asciiToStr\", {{\"int\", \"in\"}}, strType,\n\t\t\t\"unsigned char * data = (unsigned char *)malloc(1);\\n\"\n\t\t\t\"*data = in;\\n\"\n\t\t\t\"return \"+strType+\"(1, data);\\n\"\n\t\t);\n\t}\n}\n\nvoid addToProgGetInputLine(CppProgram * prog)\n{\n\tif (!prog->hasFunc(\"$getInputLine\"))\n\t{\n\t\tstring strType=prog->getTypeCode(String);\n\t\t\n\t\taddToProgCStr(prog);\n\t\t\n\t\tprog->addFunc(\"$getInputLine\", {{strType, \"prompt\"}}, strType,\n\t\t\t\"fputs(\"+prog->pnToCpp(\"$cStr\")+\"(prompt), stdout);\\n\"\n\t\t\t\"fflush(stdout);\\n\"\n\t\t\t\"size_t bufferSize = 4096;\\n\"\n\t\t\t\"char buffer[bufferSize];\\n\"\n\t\t\t\"if (fgets(buffer, bufferSize, stdin))\\n\"\n\t\t\t\"{\\n\"\n\t\t\t\"\tint size = strlen(buffer);\\n\"\n\t\t\t\"\twhile (size > 0 && buffer[size - 1] == '\\\\n')\\n\"\n\t\t\t\"\t\tsize-=1;\\n\"\n\t\t\t\"\tunsigned char * data = (unsigned char *)malloc(size);\\n\"\n\t\t\t\"\tmemcpy(data, buffer, size);\\n\"\n\t\t\t\"\treturn \"+strType+\"(size, data);\\n\"\n\t\t\t\"}\\nelse\\n{\\n\"\n\t\t\t\"\treturn \"+strType+\"(0, NULL);\\n\"\n\t\t\t\"}\"\n\t\t);\n\t}\n}\n\nvoid addToProgEqStr(CppProgram * prog)\n{\n\tif (!prog->hasFunc(\"$eqStr\"))\n\t{\n\t\tstring strType=prog->getTypeCode(String);\n\t\t\n\t\tprog->addFunc(\"$eqStr\", {{strType, \"a\"}, {strType, \"b\"}}, \"bool\",\n\t\t\t\"if (a._size != b._size)\\n\"\n\t\t\t\"\treturn false;\\n\"\n\t\t\t\"for (int i = 0; i < a._size; i++)\\n\"\n\t\t\t\"{\\n\"\n\t\t\t\"\tif (a._data[i] != b._data[i])\\n\"\n\t\t\t\"\t\treturn false;\\n\"\n\t\t\t\"}\\n\"\n\t\t\t\"return true;\\n\"\n\t\t);\n\t}\n}\n\nvoid addToProgRunCmd(CppProgram * prog)\n{\n\tif (!prog->hasFunc(\"$runCmd\"))\n\t{\n\t\taddToProgPnStr(prog);\n\t\taddToProgCStr(prog);\n\t\taddToProgConcatStr(prog);\n\t\taddToProgAsciiToStr(prog);\n\t\t\t\t\n\t\tstring strType=prog->getTypeCode(String);\n\t\t\n\t\tprog->addFunc(\"$runCmd\", {{strType, \"cmd\"}}, strType,\n\t\t\tstrType+\" result = \"+prog->pnToCpp(\"$pnStr\")+\"(\\\"\\\");\\n\"\n\t\t\t\"FILE* pipe = popen(cStr(cmd), \\\"r\\\");\\n\"\n\t\t\t\"if (!pipe)\\n\"\n\t\t\t\"\treturn result;\\n\"\n\t\t\t\"while (!feof(pipe)) {\\n\"\n\t\t\t\"\tchar c;\\n\"\n\t\t\t\"\tif ((c=getc(pipe)) != EOF)\\n\"\n\t\t\t\"\t{\\n\"\n\t\t\t\"\t\tresult=\"+prog->pnToCpp(\"$concatStr\")+\"(result, \"+prog->pnToCpp(\"$asciiToStr\")+\"(c));\\n\"\n\t\t\t\"\t}\\n\"\n\t\t\t\"}\\n\"\n\t\t\t\"pclose(pipe);\\n\"\n\t\t\t\"return result;\\n\"\n\t\t);\n\t}\n}\n\nvoid addToProgMakeIntArray(CppProgram * prog)\n{\n\tif (!prog->hasFunc(\"$makeIntArray\"))\n\t{\n\t\tstring aryType=prog->getTypeCode(IntArray);\n\t\t\n\t\tprog->addFunc(\"$makeIntArray\", {{\"int\", \"size\"}}, aryType,\n\t\t\t\"int * data = (int *)malloc(size * sizeof(int));\\n\"\n\t\t\t\"return \"+aryType+\"(size, data);\\n\"\n\t\t);\n\t}\n}\n\nvoid addToProgStrWithEscapedNames(CppProgram * prog, string str)\n{\n\tint i=0;\n\tstring buffer = \"\";\n\t\n\twhile (i < (int)str.size())\n\t{\n\t\tif (str[i] == '$')\n\t\t{\n\t\t\ti++;\n\t\t\tprog->code(buffer);\n\t\t\tbuffer = \"\";\n\t\t\twhile (i < (int)str.size())\n\t\t\t{\n\t\t\t\tchar c = str[i];\n\t\t\t\t\n\t\t\t\tif (!(\n\t\t\t\t\t(c >= '0' && c <= '9') ||\n\t\t\t\t\t(c >= 'a' && c <= 'z') ||\n\t\t\t\t\t(c >= 'A' && c <= 'Z')\n\t\t\t\t)) break;\n\t\t\t\t\n\t\t\t\tbuffer += c;\n\t\t\t\ti++;\n\t\t\t}\n\t\t\tif (buffer.empty())\n\t\t\t\tprog->code(\"$\");\n\t\t\telse\n\t\t\t\tprog->name(buffer);\n\t\t\tbuffer = \"\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbuffer += str[i];\n\t\t\ti++;\n\t\t}\n\t}\n\t\n\tprog->code(buffer);\n}\n\n\n/// setup Pinecone std lib\n\nvoid basicSetup()\n{\n\ttable=globalNamespace=NamespaceData::makeRootNamespace();\n\t\n\t//this makes a new void action after type constants have been created, if left to the original the Void type may not be set up yet\n\tvoidAction=createNewVoidAction();\n}\n\nvoid populateBasicTypes()\n{\n\tString=makeTuple(vector<NamedType>{NamedType{\"_size\", Int}, NamedType{\"_data\", Byte->getPtr()}}, false);\n\t\n\taddType(Void, \"Void\");\n\taddType(Bool, \"Bool\");\n\taddType(Byte, \"Byte\");\n\taddType(Int, \"Int\");\n\taddType(Dub, \"Dub\");\n\taddType(String, \"String\");\n\taddType(Whatev, \"Whatev\");\n}\n\nvoid populateConstants()\n{\n\ttable->addNode(AstActionWrapper::make(voidAction), \"void\");\n\t\n\tbool trueVal=true;\n\taddConst(&trueVal, Bool, \"tru\");\n\t\n\tbool falseVal=false;\n\taddConst(&falseVal, Bool, \"fls\");\n\t\n\t// version constant\n\t{\n\t\tType versionTupleType=\n\t\t\tmakeTuple(vector<NamedType>{\n\t\t\t\tNamedType{\"x\", Int},\n\t\t\t\tNamedType{\"y\", Int},\n\t\t\t\tNamedType{\"z\", Int},\n\t\t\t}, false);\n\t\t\n\t\tvoid* versionTupleData=malloc(versionTupleType->getSize());\n\t\t\n\t\tsetValInTuple(versionTupleData, versionTupleType, \"x\", VERSION_X);\n\t\tsetValInTuple(versionTupleData, versionTupleType, \"y\", VERSION_Y);\n\t\tsetValInTuple(versionTupleData, versionTupleType, \"z\", VERSION_Z);\n\t\t\n\t\taddConst(versionTupleData, versionTupleType, \"VERSION\");\n\t}\n\t\n\t// OS\n\tbool isLinux=false;\n\tbool isWindows=false;\n\tbool isUnix=false;\n\tbool isMac=false;\n\t\n\t#ifdef __linux__\n\t\tisLinux=true;\n\t\tisUnix=true;\n\t\n\t#else\n\t\t\n\t\t#ifdef _WIN32 //works forboth 32 and 64 bit systems\n\t\t\tisWindows=true;\n\t\t\n\t\t#else\n\t\t\t#ifdef __APPLE__\n\t\t\t\tisMac=true;\n\t\t\t\tisUnix=true;\n\t\t\t#endif // __APPLE__\n\t\t#endif // _WIN32\n\t\t\n\t#endif // __linux__\n\t\n\taddConst(&isLinux, Bool, \"OS_IS_LINUX\");\n\taddConst(&isWindows, Bool, \"OS_IS_WINDOWS\");\n\taddConst(&isMac, Bool, \"OS_IS_MAC\");\n\taddConst(&isUnix, Bool, \"OS_IS_UNIX\");\n\t\n\tfunc(\"IS_TRANSPILED\", Void, Void, Bool,\n\t\tretrn false;\n\t,\n\t\t\"true\"\n\t);\n\t\n\taddAction(\"arg\", Void, Int, String,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\tint right = *(int*)rightIn;\n\t\t\tif (right < (int)cmdLineArgs.size())\n\t\t\t{\n\t\t\t\treturn cppStr2PncnStr(cmdLineArgs[right]);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn cppStr2PncnStr(\"\");\n\t\t\t}\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\taddToProgPnStr(prog);\n\t\t\t\n\t\t\tprog->pushExpr();\n\t\t\t\tprog->pushExpr();\n\t\t\t\t\tprog->pushExpr();\n\t\t\t\t\t\tright->addToProg(prog);\n\t\t\t\t\tprog->popExpr();\n\t\t\t\t\tprog->code(\" < argc\");\n\t\t\t\tprog->popExpr();\n\t\t\t\tprog->code(\"?\");\n\t\t\t\tprog->pushExpr();\n\t\t\t\t\tprog->name(\"$pnStr\");\n\t\t\t\t\tprog->pushExpr();\n\t\t\t\t\t\tprog->code(\"argv[\");\n\t\t\t\t\t\tprog->pushExpr();\n\t\t\t\t\t\t\tright->addToProg(prog);\n\t\t\t\t\t\tprog->popExpr();\n\t\t\t\t\t\tprog->code(\"]\");\n\t\t\t\t\tprog->popExpr();\n\t\t\t\tprog->popExpr();\n\t\t\t\tprog->code(\":\");\n\t\t\t\tprog->pushExpr();\n\t\t\t\t\tprog->name(\"$pnStr\");\n\t\t\t\t\tprog->pushExpr();\n\t\t\t\t\t\tprog->code(\"\\\"\\\"\");\n\t\t\t\t\tprog->popExpr();\n\t\t\t\tprog->popExpr();\n\t\t\tprog->popExpr();\n\t\t}\n\t);\n\t\n\tfunc(\"argLen\", Void, Void, Int,\n\t\tretrn cmdLineArgs.size();\n\t,\n\t\t\"argc\"\n\t);\n}\n\nvoid populateOperators()\n{\n\t\n\t/// +\n\t\n\tfunc(ops->plus, Int, Int, Int,\n\t\tretrn left+right;\n\t,\n\t\t\"$. + $:\"\n\t);\n\t\n\tfunc(ops->plus, Dub, Dub, Dub,\n\t\tretrn left+right;\n\t,\n\t\t\"$. + $:\"\n\t);\n\t\n\t\n\t/// -\n\t\n\tfunc(ops->minus, Int, Int, Int,\n\t\tretrn left-right;\n\t,\n\t\t\"$. - $:\"\n\t);\n\t\n\tfunc(ops->minus, Dub, Dub, Dub,\n\t\tretrn left-right;\n\t,\n\t\t\"$. - $:\"\n\t);\n\t\n\tfunc(ops->minus, Void, Int, Int,\n\t\tretrn -right;\n\t,\n\t\t\"- $:\"\n\t);\n\t\n\tfunc(ops->minus, Void, Dub, Dub,\n\t\tretrn -right;\n\t,\n\t\t\"- $:\"\n\t);\n\t\n\t\n\t/// *\n\t\n\tfunc(ops->multiply, Int, Int, Int,\n\t\tretrn left*right;\n\t,\n\t\t\"$. * $:\"\n\t);\n\t\n\tfunc(ops->multiply, Dub, Dub, Dub,\n\t\tretrn left*right;\n\t,\n\t\t\"$. * $:\"\n\t);\n\t\n\t\n\t/// /\n\t\n\tfunc(ops->divide, Int, Int, Int,\n\t\tretrn left/right;\n\t,\n\t\t\"$. / $:\"\n\t);\n\t\n\tfunc(ops->divide, Dub, Dub, Dub,\n\t\tretrn left/right;\n\t,\n\t\t\"$. / $:\"\n\t);\n\t\n\t\n\t/// %\n\t\n\tfunc(ops->mod, Int, Int, Int,\n\t\tretrn left%right;\n\t,\n\t\t\"$. % $:\"\n\t);\n\t\n\tfunc(ops->mod, Dub, Dub, Dub,\n\t\tretrn left-int(left/right)*right;\n\t,\n\t\t\"$. - int($. / $:) * $:\"\n\t);\n\t\n\t/// =\n\t\n\tfunc(ops->equal, Bool, Bool, Bool,\n\t\tretrn left==right;\n\t,\n\t\t\"$. == $:\"\n\t);\n\t\n\tfunc(ops->equal, Int, Int, Bool,\n\t\tretrn left==right;\n\t,\n\t\t\"$. == $:\"\n\t);\n\t\n\tfunc(ops->equal, Dub, Dub, Bool,\n\t\tretrn left==right;\n\t,\n\t\t\"$. == $:\"\n\t);\n\t\n\t/// >\n\t\n\tfunc(ops->greater, Int, Int, Bool,\n\t\tretrn left>right;\n\t,\n\t\t\"$. > $:\"\n\t);\n\t\n\tfunc(ops->greater, Dub, Dub, Bool,\n\t\tretrn left>right;\n\t,\n\t\t\"$. > $:\"\n\t);\n\t\n\t// <\n\tfunc(ops->less, Int, Int, Bool,\n\t\tretrn left<right;\n\t,\n\t\t\"$. < $:\"\n\t);\n\t\n\tfunc(ops->less, Dub, Dub, Bool,\n\t\tretrn left<right;\n\t,\n\t\t\"$. < $:\"\n\t);\n\t\n\t// >=\n\tfunc(ops->greaterEq, Int, Int, Bool,\n\t\tretrn left>=right;\n\t,\n\t\t\"$. >= $:\"\n\t);\n\t\n\tfunc(ops->greaterEq, Dub, Dub, Bool,\n\t\tretrn left>=right;\n\t,\n\t\t\"$. >= $:\"\n\t);\n\t\n\t// <=\n\tfunc(ops->lessEq, Int, Int, Bool,\n\t\tretrn left<=right;\n\t,\n\t\t\"$. <= $:\"\n\t);\n\t\n\tfunc(ops->lessEq, Dub, Dub, Bool,\n\t\tretrn left<=right;\n\t,\n\t\t\"$. <= $:\"\n\t);\n\t\n\t// !\n\tfunc(ops->notOp, Void, Bool, Bool,\n\t\tretrn !right;\n\t,\n\t\t\"!$:\"\n\t);\n\t\n\tfunc(ops->notOp, Void, Int, Bool,\n\t\tretrn right==0;\n\t,\n\t\t\"$: == 0\"\n\t);\n\t\n\tfunc(ops->notOp, Void, Dub, Bool,\n\t\tretrn right==0;\n\t,\n\t\t\"$: == 0\"\n\t);\n}\n\nvoid populateConverters()\n{\n\t///initalizers\n\t\n\tfunc(\"Bool\", Void, Void, Bool,\n\t\tretrn false;\n\t,\n\t\t\"false\"\n\t);\n\t\n\tfunc(\"Int\", Void, Void, Int,\n\t\tretrn 0;\n\t,\n\t\t\"0\"\n\t);\n\t\n\tfunc(\"Dub\", Void, Void, Dub,\n\t\tretrn 0.0;\n\t,\n\t\t\"0.0\"\n\t);\n\t\n\tfunc(\"Byte\", Void, Void, Byte,\n\t\tretrn 0;\n\t,\n\t\t\"0\"\n\t);\n\t\n\t\n\t///casting\n\t\n\t//to bool\n\tfunc(\"Bool\", Void, Bool, Bool,\n\t\tretrn right\n\t,\n\t\t\"$:\"\n\t);\n\t\n\tfunc(\"Bool\", Void, Int, Bool,\n\t\tretrn right!=0\n\t,\n\t\t\"($: != 0)\"\n\t);\n\t\n\tfunc(\"Bool\", Void, Dub, Bool,\n\t\tretrn right!=0\n\t,\n\t\t\"($: != 0.0)\"\n\t);\n\t\n\tfunc(\"Bool\", Bool, Void, Bool,\n\t\tretrn left\n\t,\n\t\t\"$.\"\n\t);\n\t\n\tfunc(\"Bool\", Int, Void, Bool,\n\t\tretrn left!=0\n\t,\n\t\t\"($. != 0)\"\n\t);\n\t\n\tfunc(\"Bool\", Dub, Void, Bool,\n\t\tretrn left!=0\n\t,\n\t\t\"($. != 0.0)\"\n\t);\n\t\n\t//to Byte\n\tfunc(\"Byte\", Void, Bool, Byte,\n\t\tretrn (right?1:0)\n\t,\n\t\t\"($: ? 1 : 0)\"\n\t);\n\t\n\tfunc(\"Byte\", Void, Int, Byte,\n\t\tretrn (unsigned char)right\n\t,\n\t\t\"((unsigned char)$:)\"\n\t);\n\t\n\tfunc(\"Byte\", Bool, Void, Byte,\n\t\tretrn (left?1:0)\n\t,\n\t\t\"($. ? 1 : 0)\"\n\t);\n\t\n\tfunc(\"Byte\", Int, Void, Byte,\n\t\tretrn (unsigned char)left\n\t,\n\t\t\"((unsigned char)$.)\"\n\t);\n\t\n\t//to Int\n\tfunc(\"Int\", Void, Bool, Int,\n\t\tretrn (right?1:0)\n\t,\n\t\t\"($: ? 1 : 0)\"\n\t);\n\t\n\tfunc(\"Int\", Void, Byte, Int,\n\t\tretrn (int)right\n\t,\n\t\t\"((int)$:)\"\n\t);\n\t\n\tfunc(\"Int\", Void, Dub, Int,\n\t\tretrn (int)right\n\t,\n\t\t\"((int)$:)\"\n\t);\n\t\n\tfunc(\"Int\", Bool, Void, Int,\n\t\tretrn (left?1:0)\n\t,\n\t\t\"($. ? 1 : 0)\"\n\t);\n\t\n\tfunc(\"Int\", Byte, Void, Int,\n\t\tretrn (int)left\n\t,\n\t\t\"((int)$.)\"\n\t);\n\t\n\tfunc(\"Int\", Dub, Void, Int,\n\t\tretrn (int)left\n\t,\n\t\t\"((int)$.)\"\n\t);\n\t\n\t\n\taddAction(\"Int\", String, Void, Int,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\tint* out=(int*)malloc(sizeof(int));\n\t\t\t*out=stringToInt(pncnStr2CppStr(leftIn));\n\t\t\treturn out;\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\taddToProgStrToInt(prog);\n\t\t\t\n\t\t\tprog->name(\"$strToInt\");\n\t\t\tprog->pushExpr();\n\t\t\t\tleft->addToProg(prog);\n\t\t\tprog->popExpr();\n\t\t}\n\t);\n\t\n\t//to Dub\n\tfunc(\"Dub\", Void, Bool, Dub,\n\t\tretrn (right?1:0)\n\t,\n\t\t\"($: ? 1.0 : 0.0)\"\n\t);\n\t\t\n\tfunc(\"Dub\", Void, Int, Dub,\n\t\tretrn (double)right\n\t,\n\t\t\"((double)$:)\"\n\t);\n\t\n\tfunc(\"Dub\", Bool, Void, Dub,\n\t\tretrn (left?1:0)\n\t,\n\t\t\"($. ? 1.0 : 0.0)\"\n\t);\n\t\t\n\tfunc(\"Dub\", Int, Void, Dub,\n\t\tretrn (double)left\n\t,\n\t\t\"((double)$.)\"\n\t);\n\t\n\taddAction(\"Dub\", String, Void, Dub,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\tdouble* out=(double*)malloc(sizeof(double));\n\t\t\t*out=stringToDouble(pncnStr2CppStr(leftIn));\n\t\t\treturn out;\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\taddToProgStrToDub(prog);\n\t\t\t\n\t\t\tprog->name(\"$strToDub\");\n\t\t\tprog->pushExpr();\n\t\t\t\tleft->addToProg(prog);\n\t\t\tprog->popExpr();\n\t\t}\n\t);\n}\n\nvoid populateStdFuncs()\n{\n\t//print\n\t\n\tfunc(\"print\", Void, Void, Void,\n\t\tcout << endl;\n\t,\n\t\t\"fputs(\\\"\\\\n\\\", stdout)\"\n\t);\n\t\n\tfunc(\"print\", Void, Bool, Void,\n\t\tcout << (right?\"tru\":\"fls\") << endl;\n\t,\n\t\t\"fputs($:?\\\"tru\\\\n\\\":\\\"fls\\\\n\\\", stdout)\"\n\t);\n\t\n\tfunc(\"print\", Void, Byte, Void,\n\t\tcout << right << endl;\n\t,\n\t\t\"printf(\\\"%c\\\", $:)\"\n\t);\n\t\n\tfunc(\"print\", Void, Int, Void,\n\t\tcout << right << endl;\n\t,\n\t\t\"printf(\\\"%d\\\\n\\\", $:)\"\n\t);\n\t\n\tfunc(\"print\", Void, Dub, Void,\n\t\tcout << doubleToString(right) << endl;\n\t,\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\taddToProgDoubleToStr(prog);\n\t\t\taddToProgCStr(prog);\n\t\t\t\n\t\t\tprog->code(\"printf\");\n\t\t\tprog->pushExpr();\n\t\t\t\tprog->code(\"\\\"%s\\\\n\\\", \");\n\t\t\t\tprog->name(\"$cStr\");\n\t\t\t\tprog->pushExpr();\n\t\t\t\t\tprog->name(\"$doubleToStr\");\n\t\t\t\t\tprog->pushExpr();\n\t\t\t\t\t\tright->addToProg(prog);\n\t\t\t\t\tprog->popExpr();\n\t\t\t\tprog->popExpr();\n\t\t\tprog->popExpr();\n\t\t}\n\t);\n\t\n\taddAction(\"print\", Void, String, Void,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\tcout << pncnStr2CppStr(rightIn) << endl;\n\t\t\treturn nullptr;\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\taddToProgCStr(prog);\n\t\t\t\n\t\t\tprog->code(\"printf\");\n\t\t\tprog->pushExpr();\n\t\t\t\tprog->code(\"\\\"%s\\\\n\\\", \");\n\t\t\t\tprog->name(\"$cStr\");\n\t\t\t\tprog->pushExpr();\n\t\t\t\t\tright->addToProg(prog);\n\t\t\t\tprog->popExpr();\n\t\t\tprog->popExpr();\n\t\t}\n\t);\n}\n\nvoid populateTypeInfoFuncs()\n{\n\tglobalNamespace->addNode(\n\t\tAstWhatevToActionFactory::make(\n\t\t\t[](Type leftType, Type rightType) -> Action\n\t\t\t{\n\t\t\t\tif (leftType->isVoid() || !rightType->isVoid())\n\t\t\t\t\treturn nullptr;\n\t\t\t\t\n\t\t\t\tstring val=leftType->getName();\n\t\t\t\t\n\t\t\t\treturn lambdaAction(\n\t\t\t\t\tleftType,\n\t\t\t\t\trightType,\n\t\t\t\t\tString,\n\t\t\t\t\t\n\t\t\t\t\t[=](void* leftIn, void* rightIn) -> void*\n\t\t\t\t\t{\n\t\t\t\t\t\treturn cppStr2PncnStr(val);\n\t\t\t\t\t},\n\t\t\t\t\t\n\t\t\t\t\t[=](Action inLeft, Action inRight, CppProgram* prog)\n\t\t\t\t\t{\n\t\t\t\t\t\tvoid* pnStr=cppStr2PncnStr(val);\n\t\t\t\t\t\tconstGetAction(pnStr, String, val, globalNamespace)->addToProg(prog);\n\t\t\t\t\t\tfree(pnStr);\n\t\t\t\t\t},\n\t\t\t\t\t\"typeName\"\n\t\t\t\t);\n\t\t\t}\n\t\t),\n\t\t\"typeName\"\n\t);\n\t\n\tglobalNamespace->addNode(\n\t\tAstWhatevToActionFactory::make(\n\t\t\t[](Type leftType, Type rightType) -> Action\n\t\t\t{\n\t\t\t\tif (leftType->isVoid() || !rightType->isVoid())\n\t\t\t\t\treturn nullptr;\n\t\t\t\t\n\t\t\t\tint val=leftType->getSize();\n\t\t\t\t\n\t\t\t\treturn lambdaAction(\n\t\t\t\t\tleftType,\n\t\t\t\t\trightType,\n\t\t\t\t\tInt,\n\t\t\t\t\t\n\t\t\t\t\t[=](void* leftIn, void* rightIn) -> void*\n\t\t\t\t\t{\n\t\t\t\t\t\treturn &(*(int*)malloc(sizeof(int))=val);\n\t\t\t\t\t},\n\t\t\t\t\t\n\t\t\t\t\t[=](Action inLeft, Action inRight, CppProgram* prog)\n\t\t\t\t\t{\n\t\t\t\t\t\tconstGetAction(&val, Int, to_string(val), globalNamespace)->addToProg(prog);\n\t\t\t\t\t},\n\t\t\t\t\t\"typeSize\"\n\t\t\t\t);\n\t\t\t}\n\t\t),\n\t\t\"typeSize\"\n\t);\n}\n\nvoid populateMemManagementFuncs()\n{\n\tglobalNamespace->addNode(\n\t\tAstWhatevToActionFactory::make(\n\t\t\t[](Type leftType, Type rightType) -> Action\n\t\t\t{\n\t\t\t\tif (!leftType->isVoid() || rightType->isVoid())\n\t\t\t\t\treturn nullptr;\n\t\t\t\t\n\t\t\t\treturn lambdaAction(\n\t\t\t\t\tleftType,\n\t\t\t\t\trightType,\n\t\t\t\t\trightType->getPtr(),\n\t\t\t\t\t\n\t\t\t\t\t[=](void* leftIn, void* rightIn) -> void*\n\t\t\t\t\t{\n\t\t\t\t\t\tsize_t size=rightType->getSize();\n\t\t\t\t\t\tvoid ** dataPtr=(void**)malloc(sizeof(void*));\n\t\t\t\t\t\t*dataPtr=malloc(size);\n\t\t\t\t\t\tmemcpy(*dataPtr, rightIn, size);\n\t\t\t\t\t\treturn dataPtr;\n\t\t\t\t\t},\n\t\t\t\t\t\n\t\t\t\t\t[=](Action inLeft, Action inRight, CppProgram* prog)\n\t\t\t\t\t{\n\t\t\t\t\t\tprog->code(\"&\");\n\t\t\t\t\t\tprog->pushExpr();\n\t\t\t\t\t\t\tstring typeCode=prog->getTypeCode(rightType);\n\t\t\t\t\t\t\tprog->code(\"(*(\" + typeCode + \"*)malloc(sizeof(\" + typeCode + \")))\");\n\t\t\t\t\t\t\tprog->code(\" = \");\n\t\t\t\t\t\t\tprog->pushExpr();\n\t\t\t\t\t\t\t\tinRight->addToProg(prog);\n\t\t\t\t\t\t\tprog->popExpr();\n\t\t\t\t\t\tprog->popExpr();\n\t\t\t\t\t\t\n\t\t\t\t\t\t//\"&((*($type)malloc(sizeof($type)))=($data))\"\n\t\t\t\t\t},\n\t\t\t\t\t\"new\"\n\t\t\t\t);\n\t\t\t}\n\t\t),\n\t\t\"new\"\n\t);\n\t\n\tglobalNamespace->addNode(\n\t\tAstWhatevToActionFactory::make(\n\t\t\t[](Type leftType, Type rightType) -> Action\n\t\t\t{\n\t\t\t\tif (leftType->getType()!=TypeBase::PTR || leftType->isVoid() || !rightType->isVoid())\n\t\t\t\t\treturn nullptr;\n\t\t\t\t\n\t\t\t\treturn lambdaAction(\n\t\t\t\t\tleftType,\n\t\t\t\t\trightType,\n\t\t\t\t\tleftType->getSubType(),\n\t\t\t\t\t\n\t\t\t\t\t[=](void* leftIn, void* rightIn) -> void*\n\t\t\t\t\t{\n\t\t\t\t\t\tsize_t size=leftType->getSubType()->getSize();\n\t\t\t\t\t\tvoid * data=malloc(size);\n\t\t\t\t\t\tmemcpy(data, *(void**)leftIn, size);\n\t\t\t\t\t\treturn data;\n\t\t\t\t\t},\n\t\t\t\t\t\n\t\t\t\t\t[=](Action inLeft, Action inRight, CppProgram* prog)\n\t\t\t\t\t{\n\t\t\t\t\t\tprog->code(\"*\");\n\t\t\t\t\t\tprog->pushExpr();\n\t\t\t\t\t\t\tinLeft->addToProg(prog);\n\t\t\t\t\t\tprog->popExpr();\n\t\t\t\t\t},\n\t\t\t\t\t\"dif\"\n\t\t\t\t);\n\t\t\t}\n\t\t),\n\t\t\"dif\"\n\t);\n\t\n\tglobalNamespace->addNode(\n\t\tAstWhatevToActionFactory::make(\n\t\t\t[](Type leftType, Type rightType) -> Action\n\t\t\t{\n\t\t\t\tif (leftType->getType()!=TypeBase::PTR || !rightType->matches(leftType->getSubType()))\n\t\t\t\t\treturn nullptr;\n\t\t\t\t\n\t\t\t\treturn lambdaAction(\n\t\t\t\t\tleftType,\n\t\t\t\t\trightType,\n\t\t\t\t\tVoid,\n\t\t\t\t\t\n\t\t\t\t\t[=](void* leftIn, void* rightIn) -> void*\n\t\t\t\t\t{\n\t\t\t\t\t\tmemcpy(*(void**)leftIn, rightIn, rightType->getSize());\n\t\t\t\t\t\treturn nullptr;\n\t\t\t\t\t},\n\t\t\t\t\t\n\t\t\t\t\t[=](Action inLeft, Action inRight, CppProgram* prog)\n\t\t\t\t\t{\n\t\t\t\t\t\tprog->code(\"*\");\n\t\t\t\t\t\tprog->pushExpr();\n\t\t\t\t\t\t\tinLeft->addToProg(prog);\n\t\t\t\t\t\tprog->popExpr();\n\t\t\t\t\t\tprog->code(\" = \");\n\t\t\t\t\t\tprog->pushExpr();\n\t\t\t\t\t\t\tinRight->addToProg(prog);\n\t\t\t\t\t\tprog->popExpr();\n\t\t\t\t\t},\n\t\t\t\t\t\"dif\"\n\t\t\t\t);\n\t\t\t}\n\t\t),\n\t\t\"dif\"\n\t);\n}\n\nvoid populateStringFuncs()\n{\n\tauto destructorLambda=LAMBDA_HEADER\n\t\t{\n\t\t\t//if (getValFromTuple<char*>(rightIn, String, \"_data\")[0]==1)\n\t\t\t//\terror.log(\"double free detected\", JSYK);\n\t\t\t//getValFromTuple<char*>(rightIn, String, \"_data\")[0]=1;\n\t\t\tfree(getValFromTuple<char*>(rightIn, String, \"_data\"));\n\t\t\treturn nullptr;\n\t\t};\n\t\n\taddAction(\"__destroy__\", Void, String, Void,\n\t\tdestructorLambda,\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\tprog->code(\"free\");\n\t\t\tprog->pushExpr();\n\t\t\t\tright->addToProg(prog);\n\t\t\t\tprog->code(\"._data\");\n\t\t\tprog->popExpr();\n\t\t}\n\t);\n\t\n\taddAction(\"__copy__\", Void, String, String,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\tint size=getValFromTuple<int>(rightIn, String, \"_size\");\n\t\t\tvoid* newData=malloc(size);\n\t\t\tmemcpy(newData, getValFromTuple<void*>(rightIn, String, \"_data\"), size);\n\t\t\tsetValInTuple(rightIn, String, \"_data\", newData);\n\t\t\tvoid* out=malloc(String->getSize());\n\t\t\tmemcpy(out, rightIn, String->getSize());\n\t\t\treturn out;\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\tif (!prog->hasFunc(\"$copyStr\"))\n\t\t\t{\n\t\t\t\tstring strType=prog->getTypeCode(String);\n\t\t\t\t\n\t\t\t\tprog->addFunc(\"$copyStr\", {{strType, \"in\"}}, strType,\n\t\t\t\t\t\"unsigned char* newData=(unsigned char*)malloc(in._size);\\n\"\n\t\t\t\t\t\"memcpy(newData, in._data, in._size);\\n\"\n\t\t\t\t\t\"in._data=newData;\\n\"\n\t\t\t\t\t\"return in;\\n\"\n\t\t\t\t);\n\t\t\t}\n\t\t\t\n\t\t\tprog->name(\"$copyStr\");\n\t\t\tprog->pushExpr();\n\t\t\t\tright->addToProg(prog);\n\t\t\tprog->popExpr();\n\t\t}\n\t);\n\t\n\taddAction(\"String\", Void, Void, String,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\treturn cppStr2PncnStr(\"\");\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\tprog->code(prog->getTypeCode(String)+\"(0, nullptr)\");\n\t\t}\n\t);\n\t\n\taddAction(\"String\", String, Void, String,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\treturn cppStr2PncnStr(pncnStr2CppStr(leftIn));\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\tleft->addToProg(prog);\n\t\t}\n\t);\n\t\n\taddAction(\"String\", Int, Void, String,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\treturn cppStr2PncnStr(to_string(*((int*)leftIn)));\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\taddToProgIntToStr(prog);\n\t\t\t\n\t\t\tprog->name(\"$intToStr\");\n\t\t\tprog->pushExpr();\n\t\t\t\tleft->addToProg(prog);\n\t\t\tprog->popExpr();\n\t\t}\n\t);\n\t\n\taddAction(\"String\", Dub, Void, String,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\treturn cppStr2PncnStr(doubleToString(*((double*)leftIn)));\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\taddToProgDoubleToStr(prog);\n\t\t\t\n\t\t\tprog->name(\"$doubleToStr\");\n\t\t\tprog->pushExpr();\n\t\t\t\tleft->addToProg(prog);\n\t\t\tprog->popExpr();\n\t\t}\n\t);\n\t\n\taddAction(\"String\", Bool, Void, String,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\tif (*((bool*)leftIn))\n\t\t\t{\n\t\t\t\treturn cppStr2PncnStr(\"tru\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn cppStr2PncnStr(\"fls\");\n\t\t\t}\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\taddToProgPnStr(prog);\n\t\t\t\n\t\t\tprog->name(\"$pnStr\");\n\t\t\tprog->pushExpr();\n\t\t\t\tprog->pushExpr();\n\t\t\t\t\tleft->addToProg(prog);\n\t\t\t\tprog->popExpr();\n\t\t\t\tprog->code(\" ? \\\"tru\\\" : \\\"fls\\\"\");\n\t\t\tprog->popExpr();\n\t\t}\n\t);\n\t\n\taddAction(\"len\", String, Void, Int,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\tint* out=(int*)malloc(sizeof(int));\n\t\t\t*out=getValFromTuple<int>(leftIn, String, \"_size\");\n\t\t\treturn out;\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\tgetElemFromTupleAction(String, \"_size\")->addToProg(left, voidAction, prog);\n\t\t}\n\t);\n\t\n\taddAction(\"ascii\", Int, Void, String,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\tint val=*((int*)leftIn);\n\t\t\tif (val<0 || val>=256)\n\t\t\t{\n\t\t\t\tthrow PineconeError(\"tried to make ascii string out of value \"+to_string(val), RUNTIME_ERROR);\n\t\t\t}\n\t\t\tstring out;\n\t\t\tout+=(char)val;\n\t\t\treturn cppStr2PncnStr(out);\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\taddToProgAsciiToStr(prog);\n\t\t\t\n\t\t\tprog->name(\"$asciiToStr\");\n\t\t\tprog->pushExpr();\n\t\t\t\tleft->addToProg(prog);\n\t\t\tprog->popExpr();\n\t\t}\n\t);\n\t\n\taddAction(\"at\", String, Int, Int,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\tint index=*((int*)rightIn);\n\t\t\tint * out=(int*)malloc(sizeof(int));\n\t\t\tstring str=pncnStr2CppStr(leftIn);\n\t\t\tif (index<0 || index>=int(str.size()))\n\t\t\t{\n\t\t\t\tthrow PineconeError(\"tried to access location \"+to_string(index)+\" in string \"+to_string(str.size())+\" long\", RUNTIME_ERROR);\n\t\t\t}\n\t\t\t*out=str[index];\n\t\t\treturn out;\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\tprog->code(\"(int)\");\n\t\t\tgetElemFromTupleAction(String, \"_data\")->addToProg(left, voidAction, prog);\n\t\t\tprog->code(\"[\");\n\t\t\tprog->pushExpr();\n\t\t\t\tright->addToProg(prog);\n\t\t\tprog->popExpr();\n\t\t\tprog->code(\"]\");\n\t\t}\n\t);\n\t\n\taddAction(\"sub\", String, makeTuple(vector<NamedType>{NamedType{\"a\", Int}, NamedType{\"b\", Int}}, true), String,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\tType RightType=makeTuple(vector<NamedType>{NamedType{\"a\", Int}, NamedType{\"b\", Int}}, true);\n\t\t\tint start=getValFromTuple<int>(rightIn, RightType, \"a\");\n\t\t\tint end=getValFromTuple<int>(rightIn, RightType, \"b\");\n\t\t\tstring str=pncnStr2CppStr(leftIn);\n\t\t\tif (start<0 || end>int(str.size()) || start>end)\n\t\t\t{\n\t\t\t\tthrow PineconeError(\"invalid arguments sent to String.sub\", RUNTIME_ERROR);\n\t\t\t}\n\t\t\treturn cppStr2PncnStr(str.substr(start, end-start));\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\taddToProgSubStr(prog);\n\t\t\t\n\t\t\tprog->name(\"$subStr\");\n\t\t\tprog->pushExpr();\n\t\t\t\tleft->addToProg(prog);\n\t\t\t\tprog->code(\", \");\n\t\t\t\tgetElemFromTupleAction(right->getReturnType(), \"a\")->addToProg(right, voidAction, prog);\n\t\t\t\tprog->code(\", \");\n\t\t\t\tgetElemFromTupleAction(right->getReturnType(), \"b\")->addToProg(right, voidAction, prog);\n\t\t\tprog->popExpr();\n\t\t}\n\t);\n\t\n\taddAction(\"input\", String, Void, String,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\tstring in;\n\t\t\tcout << pncnStr2CppStr(leftIn);\n\t\t\tstd::getline (std::cin, in);\n\t\t\treturn cppStr2PncnStr(in);\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\taddToProgGetInputLine(prog);\n\t\t\t\n\t\t\tprog->name(\"$getInputLine\");\n\t\t\tprog->pushExpr();\n\t\t\t\tleft->addToProg(prog);\n\t\t\tprog->popExpr();\n\t\t}\n\t);\n\t\n\taddAction(ops->plus, String, String, String,\n\t\t[=](void* leftIn, void* rightIn)->void*\n\t\t{\n\t\t\tvoid* out=cppStr2PncnStr(pncnStr2CppStr(leftIn)+pncnStr2CppStr(rightIn));\n\t\t\t//free(destructorLambda(nullptr, leftIn));\n\t\t\t//free(destructorLambda(nullptr, rightIn));\n\t\t\treturn out;\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\taddToProgConcatStr(prog);\n\t\t\t\n\t\t\tprog->name(\"$concatStr\");\n\t\t\tprog->pushExpr();\n\t\t\t\tleft->addToProg(prog);\n\t\t\t\tprog->code(\", \");\n\t\t\t\tright->addToProg(prog);\n\t\t\tprog->popExpr();\n\t\t}\n\t);\n\t\n\taddAction(ops->equal, String, String, Bool,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\tbool* out=(bool*)malloc(sizeof(bool));\n\t\t\t*out=pncnStr2CppStr(leftIn)==pncnStr2CppStr(rightIn);\n\t\t\treturn out;\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\taddToProgEqStr(prog);\n\t\t\t\n\t\t\tprog->name(\"$eqStr\");\n\t\t\tprog->pushExpr();\n\t\t\t\tleft->addToProg(prog);\n\t\t\t\tprog->code(\", \");\n\t\t\t\tright->addToProg(prog);\n\t\t\tprog->popExpr();\n\t\t}\n\t);\n}\n\nvoid populateArrayFuncs()\n{\n\tTupleTypeMaker maker;\n\tmaker.add(\"_size\", Int);\n\tmaker.add(\"_capacity\", Int);\n\tmaker.add(\"_data\", Whatev->getPtr());\n\tArray=maker.get(false);\n\t\n\taddType(Array, \"Array\");\n\t\n\tglobalNamespace->addNode(\n\t\tAstWhatevToActionFactory::make(\n\t\t\t[](Type leftType, Type rightType) -> Action\n\t\t\t{\n\t\t\t\tassert leftType->isCreatable() && rightType->isVoid()\n\t\t\t\t\totherwise return nullptr;\n\t\t\t\t\n\t\t\t\tType contentsType=leftType;\n\t\t\t\tType arrayType=Array->actuallyIs(makeTuple({{\"a\", Int}, {\"b\", Int}, {\"c\", contentsType->getPtr()}}, true))->getPtr();\n\t\t\t\t\n\t\t\t\treturn lambdaAction(\n\t\t\t\t\tleftType,\n\t\t\t\t\trightType,\n\t\t\t\t\tarrayType,\n\t\t\t\t\t\n\t\t\t\t\t[=](void* leftIn, void* rightIn) -> void*\n\t\t\t\t\t{\n\t\t\t\t\t\tvoid* out=malloc(arrayType->getSize());\n\t\t\t\t\t\tsetValInTuple(out, arrayType, \"_size\", 0);\n\t\t\t\t\t\tsetValInTuple(out, arrayType, \"_capacity\", 0);\n\t\t\t\t\t\tsetValInTuple<void*>(out, arrayType, \"_data\", nullptr);\n\t\t\t\t\t\treturn out;\n\t\t\t\t\t},\n\t\t\t\t\t\n\t\t\t\t\t[=](Action inLeft, Action inRight, CppProgram* prog)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow PineconeError(\"not yet implemented\", INTERNAL_ERROR);\n\t\t\t\t\t},\n\t\t\t\t\t\n\t\t\t\t\t\"Array\"\n\t\t\t\t);\n\t\t\t}\n\t\t),\n\t\t\"Array\"\n\t);\n\t\n\tglobalNamespace->addNode(\n\t\tAstWhatevToActionFactory::make(\n\t\t\t[](Type leftType, Type rightType) -> Action\n\t\t\t{\n\t\t\t\tassert leftType->matches(Array)\n\t\t\t\t\totherwise return nullptr;\n\t\t\t\t\n\t\t\t\tType arrayType=Array->actuallyIs(leftType->getPtr());\n\t\t\t\tType contentsType=arrayType->getSubType(\"_data\").type->getSubType();\n\t\t\t\t\n\t\t\t\tassert rightType->matches(contentsType)\n\t\t\t\t\totherwise return nullptr;\n\t\t\t\t\n\t\t\t\treturn lambdaAction(\n\t\t\t\t\tleftType,\n\t\t\t\t\trightType,\n\t\t\t\t\tVoid,\n\t\t\t\t\t\n\t\t\t\t\t[=](void* leftIn, void* rightIn) -> void*\n\t\t\t\t\t{\n\t\t\t\t\t\tint size=getValFromTuple<int>(leftIn, arrayType, \"_size\");\n\t\t\t\t\t\tint capacity=getValFromTuple<int>(leftIn, arrayType, \"_capacity\");\n\t\t\t\t\t\tvoid* data=getValFromTuple<void*>(leftIn, arrayType, \"_data\");\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (size+1>capacity)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (capacity<1000)\n\t\t\t\t\t\t\t\tcapacity=1000;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tcapacity*=2;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tsetValInTuple<int>(leftIn, arrayType, \"_capacity\", capacity);\n\t\t\t\t\t\t\tvoid* newData=malloc(capacity*contentsType->getSize());\n\t\t\t\t\t\t\tmemcpy(newData, data, size*contentsType->getSize());\n\t\t\t\t\t\t\tfree(data);\n\t\t\t\t\t\t\tdata=newData;\n\t\t\t\t\t\t\tsetValInTuple<void*>(leftIn, arrayType, \"_data\", data);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tsetValInTuple<int>(leftIn, arrayType, \"_size\", size+1);\n\t\t\t\t\t\tmemcpy((char*)data+size*contentsType->getSize(), rightIn, contentsType->getSize());\n\t\t\t\t\t\t\n\t\t\t\t\t\treturn nullptr;\n\t\t\t\t\t},\n\t\t\t\t\t\n\t\t\t\t\t[=](Action inLeft, Action inRight, CppProgram* prog)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow PineconeError(\"not yet implemented\", INTERNAL_ERROR);\n\t\t\t\t\t},\n\t\t\t\t\t\"append\"\n\t\t\t\t);\n\t\t\t}\n\t\t),\n\t\t\"append\"\n\t);\n\t\n\tglobalNamespace->addNode(\n\t\tAstWhatevToActionFactory::make(\n\t\t\t[](Type leftType, Type rightType) -> Action\n\t\t\t{\n\t\t\t\tassert leftType->matches(Array->getPtr()) && rightType->matches(Int)\n\t\t\t\t\totherwise return nullptr;\n\t\t\t\t\n\t\t\t\tType arrayType=Array->actuallyIs(leftType->getSubType());\n\t\t\t\tType contentsType=arrayType->getSubType(\"_data\").type->getSubType();\n\t\t\t\tsize_t elemSize=contentsType->getSize();\n\t\t\t\t\n\t\t\t\treturn lambdaAction(\n\t\t\t\t\tleftType,\n\t\t\t\t\trightType,\n\t\t\t\t\tcontentsType,\n\t\t\t\t\t\n\t\t\t\t\t[=](void* leftIn, void* rightIn) -> void*\n\t\t\t\t\t{\n\t\t\t\t\t\tint size=getValFromTuple<int>(leftIn, arrayType, \"_size\");\n\t\t\t\t\t\tif (*(int*)rightIn<0 || *(int*)rightIn>=size)\n\t\t\t\t\t\t\tthrow PineconeError(\"index out of bounds, tried to get element at position \"+to_string(*(int*)rightIn)+\" in array \"+to_string(size)+\" long\", RUNTIME_ERROR);\n\t\t\t\t\t\t\n\t\t\t\t\t\tvoid* out=malloc(contentsType->getSize());\n\t\t\t\t\t\tmemcpy(out, getValFromTuple<char*>(leftIn, arrayType, \"_data\")+(*(int*)rightIn)*elemSize, elemSize);\n\t\t\t\t\t\treturn out;\n\t\t\t\t\t},\n\t\t\t\t\t\n\t\t\t\t\t[=](Action inLeft, Action inRight, CppProgram* prog)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow PineconeError(\"not yet implemented\", INTERNAL_ERROR);\n\t\t\t\t\t},\n\t\t\t\t\t\"get\"\n\t\t\t\t);\n\t\t\t}\n\t\t),\n\t\t\"get\"\n\t);\n\t\n\tglobalNamespace->addNode(\n\t\tAstWhatevToActionFactory::make(\n\t\t\t[](Type leftType, Type rightType) -> Action\n\t\t\t{\n\t\t\t\tType arrayType=Array->actuallyIs(leftType->getSubType());\n\t\t\t\tType contentsType=arrayType->getSubType(\"_data\").type->getSubType();\n\t\t\t\t\n\t\t\t\tType inputType=makeTuple({{\"index\", Int}, {\"value\", contentsType}}, true);\n\t\t\t\t\n\t\t\t\tassert leftType->getSubType()->matches(Array) && rightType->matches(inputType)\n\t\t\t\t\totherwise return nullptr;\n\t\t\t\t\n\t\t\t\tsize_t elemSize=contentsType->getSize();\n\t\t\t\t\n\t\t\t\treturn lambdaAction(\n\t\t\t\t\tleftType,\n\t\t\t\t\trightType,\n\t\t\t\t\tcontentsType,\n\t\t\t\t\t\n\t\t\t\t\t[=](void* leftIn, void* rightIn) -> void*\n\t\t\t\t\t{\n\t\t\t\t\t\tint size=getValFromTuple<int>(leftIn, arrayType, \"_size\");\n\t\t\t\t\t\tint index=getValFromTuple<int>(rightIn, inputType, \"index\");\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (index<0 || index>=size)\n\t\t\t\t\t\t\tthrow PineconeError(\"index out of bounds, tried to set element at position \"+to_string(index)+\" in array \"+to_string(size)+\" long\", RUNTIME_ERROR);\n\t\t\t\t\t\t\n\t\t\t\t\t\tchar* data=getValFromTuple<char*>(leftIn, arrayType, \"_data\");\n\t\t\t\t\t\t\n\t\t\t\t\t\tmemcpy(data+index*elemSize, (char*)rightIn+inputType->getSubType(\"value\").offset, contentsType->getSize());\n\t\t\t\t\t\t\n\t\t\t\t\t\treturn nullptr;\n\t\t\t\t\t},\n\t\t\t\t\t\n\t\t\t\t\t[=](Action inLeft, Action inRight, CppProgram* prog)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow PineconeError(\"not yet implemented\", INTERNAL_ERROR);\n\t\t\t\t\t},\n\t\t\t\t\t\"set\"\n\t\t\t\t);\n\t\t\t}\n\t\t),\n\t\t\"set\"\n\t);\n\t\n\tglobalNamespace->addNode(\n\t\tAstWhatevToActionFactory::make(\n\t\t\t[](Type leftType, Type rightType) -> Action\n\t\t\t{\n\t\t\t\tassert leftType->matches(Array) && rightType->isVoid()\n\t\t\t\t\totherwise return nullptr;\n\t\t\t\t\n\t\t\t\tType arrayType=Array->actuallyIs(leftType);\n\t\t\t\tType contentsType=arrayType->getSubType(\"_data\").type->getSubType();\n\t\t\t\t\n\t\t\t\treturn lambdaAction(\n\t\t\t\t\tleftType,\n\t\t\t\t\trightType,\n\t\t\t\t\tInt,\n\t\t\t\t\t\n\t\t\t\t\t[=](void* leftIn, void* rightIn) -> void*\n\t\t\t\t\t{\n\t\t\t\t\t\tint* out=(int*)malloc(sizeof(int));\n\t\t\t\t\t\t*out=getValFromTuple<int>(leftIn, arrayType, \"_size\");\n\t\t\t\t\t\treturn out;\n\t\t\t\t\t},\n\t\t\t\t\t\n\t\t\t\t\t[=](Action inLeft, Action inRight, CppProgram* prog)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow PineconeError(\"not yet implemented\", INTERNAL_ERROR);\n\t\t\t\t\t},\n\t\t\t\t\t\"len\"\n\t\t\t\t);\n\t\t\t}\n\t\t),\n\t\t\"len\"\n\t);\n\t\n\tglobalNamespace->addNode(\n\t\tAstWhatevToActionFactory::make(\n\t\t\t[](Type leftType, Type rightType) -> Action\n\t\t\t{\n\t\t\t\tassert leftType->isVoid() && rightType->matches(Array)\n\t\t\t\t\totherwise return nullptr;\n\t\t\t\t\n\t\t\t\tType arrayType=Array->actuallyIs(rightType);\n\t\t\t\tType contentsType=arrayType->getSubType(\"_data\").type->getSubType();\n\t\t\t\tsize_t elemSize=contentsType->getSize();\n\t\t\t\t\n\t\t\t\treturn lambdaAction(\n\t\t\t\t\tVoid,\n\t\t\t\t\trightType,\n\t\t\t\t\trightType,\n\t\t\t\t\t\n\t\t\t\t\t[=](void* leftIn, void* rightIn) -> void*\n\t\t\t\t\t{\n\t\t\t\t\t\t//error.log(\"Array destroyer called\", JSYK);\n\t\t\t\t\t\tint size=getValFromTuple<int>(rightIn, arrayType, \"_size\");\n\t\t\t\t\t\tvoid* newData=malloc(elemSize*size);\n\t\t\t\t\t\tvoid* oldData=getValFromTuple<void*>(rightIn, arrayType, \"_data\");\n\t\t\t\t\t\tmemcpy(newData, oldData, elemSize*size);\n\t\t\t\t\t\tsetValInTuple(rightIn, arrayType, \"_data\", newData);\n\t\t\t\t\t\tvoid* out=malloc(arrayType->getSize());\n\t\t\t\t\t\tmemcpy(out, rightIn, arrayType->getSize());\n\t\t\t\t\t\treturn out;\n\t\t\t\t\t},\n\t\t\t\t\t\n\t\t\t\t\t[=](Action inLeft, Action inRight, CppProgram* prog)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow PineconeError(\"not yet implemented\", INTERNAL_ERROR);\n\t\t\t\t\t},\n\t\t\t\t\t\"__copy__\"\n\t\t\t\t);\n\t\t\t}\n\t\t),\n\t\t\"__copy__\"\n\t);\n\t\n\tglobalNamespace->addNode(\n\t\tAstWhatevToActionFactory::make(\n\t\t\t[](Type leftType, Type rightType) -> Action\n\t\t\t{\n\t\t\t\tassert leftType->isVoid() && rightType->matches(Array)\n\t\t\t\t\totherwise return nullptr;\n\t\t\t\t\n\t\t\t\tType arrayType=Array->actuallyIs(rightType);\n\t\t\t\t\n\t\t\t\treturn lambdaAction(\n\t\t\t\t\tVoid,\n\t\t\t\t\trightType,\n\t\t\t\t\tVoid,\n\t\t\t\t\t\n\t\t\t\t\t[=](void* leftIn, void* rightIn) -> void*\n\t\t\t\t\t{\n\t\t\t\t\t\t//error.log(\"Array destroyer called\", JSYK);\n\t\t\t\t\t\t\n\t\t\t\t\t\tfree(getValFromTuple<void*>(rightIn, arrayType, \"_data\"));\n\t\t\t\t\t\treturn nullptr;\n\t\t\t\t\t},\n\t\t\t\t\t\n\t\t\t\t\t[=](Action inLeft, Action inRight, CppProgram* prog)\n\t\t\t\t\t{\n\t\t\t\t\t\tthrow PineconeError(\"not yet implemented\", INTERNAL_ERROR);\n\t\t\t\t\t},\n\t\t\t\t\t\"__destroy__\"\n\t\t\t\t);\n\t\t\t}\n\t\t),\n\t\t\"__destroy__\"\n\t);\n}\n\nvoid populateIntArrayAndFuncs()\n{\n\tTupleTypeMaker maker;\n\tmaker.add(\"_size\", Int);\n\tmaker.add(\"_data\", Int->getPtr());\n\tIntArray=maker.get(false);\n\t\n\taddType(IntArray, \"IntArray\");\n\t\n\t//func(\"IntArray\", IntArray, Void, Int,\n\t//\tretrn Tuple(right, (double)((int*)malloc(Int->getSize()*right)));\n\t//);\n\t\n\taddAction(\"IntArray\", Void, Int, IntArray, LAMBDA_HEADER\n\t\t{\n\t\t\tchar* out=(char*)malloc(IntArray->getSize());\n\t\t\tint sizeIn=*(int*)rightIn;\n\t\t\tint* intPtrData=(int *)malloc(Int->getSize()*sizeIn);\n\t\t\tsetValInTuple<int>(out, IntArray, \"_size\", sizeIn);\n\t\t\tsetValInTuple<int *>(out, IntArray, \"_data\", intPtrData);\n\t\t\treturn out;\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\taddToProgMakeIntArray(prog);\n\t\t\tprog->name(\"$makeIntArray\");\n\t\t\tprog->pushExpr();\n\t\t\t\tright->addToProg(prog);\n\t\t\tprog->popExpr();\n\t\t}\n\t);\n\t\n\taddAction(\"len\", IntArray, Void, Int,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\tint* out=(int*)malloc(sizeof(int));\n\t\t\t*out=getValFromTuple<int>(leftIn, IntArray, \"_size\");\n\t\t\treturn out;\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\tgetElemFromTupleAction(IntArray, \"_size\")->addToProg(left, voidAction, prog);\n\t\t}\n\t);\n\t\n\taddAction(\"get\", IntArray, Int, Int, LAMBDA_HEADER\n\t\t{\n\t\t\tint pos=*(int*)rightIn;\n\t\t\tint size=getValFromTuple<int>(leftIn, IntArray, \"_size\");\n\t\t\tif (pos<0 || pos>=size)\n\t\t\t\tthrow PineconeError(\"tried to acces position \"+to_string(pos)+\" of array \"+to_string(size)+\" long\", RUNTIME_ERROR);\n\t\t\tint* arrayPtr=getValFromTuple<int*>(leftIn, IntArray, \"_data\");\n\t\t\tint val=*(arrayPtr+pos);\n\t\t\tint* out=(int*)malloc(sizeof(int));\n\t\t\t*out=val;\n\t\t\treturn out;\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\tgetElemFromTupleAction(IntArray, \"_data\")->addToProg(left, voidAction, prog);\n\t\t\tprog->code(\"[\");\n\t\t\tprog->pushExpr();\n\t\t\t\tright->addToProg(prog);\n\t\t\tprog->popExpr();\n\t\t\tprog->code(\"]\");\n\t\t}\n\t);\n\t\n\taddAction(\"set\", IntArray, PNCN_Tuple(Int, Int), Void,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\tType rightType=PNCN_Tuple(Int, Int);\n\t\t\tint pos=getValFromTuple<int>(rightIn, rightType, \"a\");\n\t\t\tint size=getValFromTuple<int>(leftIn, IntArray, \"_size\");\n\t\t\tif (pos<0 || pos>=size)\n\t\t\t\tthrow PineconeError(\"tried to set value at position \"+to_string(pos)+\" of array \"+to_string(size)+\" long\", RUNTIME_ERROR);\n\t\t\tint val=getValFromTuple<int>(rightIn, rightType, \"b\");\n\t\t\tint* arrayPtr=getValFromTuple<int*>(leftIn, IntArray, \"_data\");\n\t\t\t*(arrayPtr+pos)=val;\n\t\t\treturn nullptr;\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\tgetElemFromTupleAction(IntArray, \"_data\")->addToProg(left, voidAction, prog);\n\t\t\tprog->code(\"[\");\n\t\t\tprog->pushExpr();\n\t\t\t\tgetElemFromTupleAction(right->getReturnType(), \"a\")->addToProg(right, voidAction, prog);\n\t\t\tprog->popExpr();\n\t\t\tprog->code(\"]\");\n\t\t\tprog->code(\" = \");\n\t\t\tgetElemFromTupleAction(right->getReturnType(), \"b\")->addToProg(right, voidAction, prog);\n\t\t}\n\t);\n}\n\nvoid populateNonStdFuncs()\n{\n\tfunc(\"printc\", Void, Int, Void,\n\t\t\tputchar((char)right)\n\t\t,\n\t\t\t\"putchar($:)\"\n\t\t);\n\t\n\tfunc(\"inputc\", Void, Void, Int,\n\t\t\tretrn getchar()\n\t\t,\n\t\t\t\"getchar()\"\n\t\t);\n\t\n\tfunc(\"inputInt\", Void, Void, Int,\n\t\t\tint val;\n\t\t\tstd::cin >> val;\n\t\t\tretrn val;\n\t\t,\n\t\t\tADD_CPP_HEADER\n\t\t\t{\n\t\t\t\tif (!prog->hasFunc(\"-getIntInput\"))\n\t\t\t\t{\n\t\t\t\t\tprog->pushFunc(\"-getIntInput\", Void, Void, Int);\n\t\t\t\t\t\tprog->declareVar(\"tmp\", Int);\n\t\t\t\t\t\tprog->code(\"scanf\");\n\t\t\t\t\t\tprog->pushExpr();\n\t\t\t\t\t\t\tprog->code(\"\\\"%d\\\", &\");\n\t\t\t\t\t\t\tprog->name(\"tmp\");\n\t\t\t\t\t\tprog->popExpr();\n\t\t\t\t\t\tprog->endln();\n\t\t\t\t\t\tprog->code(\"return \");\n\t\t\t\t\t\tprog->name(\"tmp\");\n\t\t\t\t\t\tprog->endln();\n\t\t\t\t\tprog->popFunc();\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tprog->name(\"-getIntInput\");\n\t\t\t\tprog->code(\"()\");\n\t\t\t}\n\t\t);\n\t\n\taddAction(\"runCmd\", Void, String, String,\n\t\tLAMBDA_HEADER\n\t\t{\n\t\t\treturn cppStr2PncnStr(runCmd(pncnStr2CppStr(rightIn)));\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\taddToProgRunCmd(prog);\n\t\t\tprog->name(\"$runCmd\");\n\t\t\tprog->pushExpr();\n\t\t\t\tright->addToProg(prog);\n\t\t\tprog->popExpr();\n\t\t}\n\t);\n}\n\nvoid populateCppInterfaceFuncs()\n{\n\taddAction(\"cppCode\", Void, String, Void, LAMBDA_HEADER\n\t\t{\n\t\t\tthrow PineconeError(\"you can't run interpreter with code that uses 'cppCode'\", SOURCE_ERROR);\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\tprog->pushBlock();\n\t\t\taddToProgStrWithEscapedNames(prog, pncnStr2CppStr(right->execute(nullptr, nullptr)));\n\t\t\tprog->popBlock();\n\t\t}\n\t);\n\t\n\taddAction(\"cppHead\", Void, String, Void, LAMBDA_HEADER\n\t\t{\n\t\t\tthrow PineconeError(\"you can't run interpreter with code that uses 'cppHead'\", SOURCE_ERROR);\n\t\t},\n\t\tADD_CPP_HEADER\n\t\t{\n\t\t\tprog->addHeadCode(pncnStr2CppStr(right->execute(nullptr, nullptr)));\n\t\t}\n\t);\n}\n\nvoid populatePineconeStdLib()\n{\n\tbasicSetup();\n\tpopulateBasicTypes();\n\tpopulateConstants();\n\tpopulateOperators();\n\tpopulateConverters();\n\tpopulateStdFuncs();\n\tpopulateTypeInfoFuncs();\n\tpopulateMemManagementFuncs();\n\tpopulateStringFuncs();\n\tpopulateIntArrayAndFuncs();\n\tpopulateArrayFuncs();\n\tpopulateNonStdFuncs();\n\tpopulateCppInterfaceFuncs();\n}\n\n\n"
  },
  {
    "path": "src/ResolveLiteral.cpp",
    "content": "#include \"../h/Action.h\"\n#include \"../h/Token.h\"\n#include \"../h/ErrorHandler.h\"\n#include \"../h/Namespace.h\"\n\nextern Namespace globalNamespace;\n\nAction resolveIntLiteral(Token token, Type type)\n{\n\tstring in=token->getText();\n\t\n\tint val=0;\n\t\n\tfor (auto i=in.begin(); i!=in.end(); ++i)\n\t{\n\t\tif (*i<'0' || *i>'9')\n\t\t{\n\t\t\terror.log(string() + \"bad character '\" + *i + \"' found in number '\" + in + \"'\", SOURCE_ERROR, token);\n\t\t\treturn nullptr;\n\t\t}\n\t\t\n\t\tval=val*10+(*i-'0');\n\t}\n\t\n\tif (type==Bool)\n\t{\n\t\tbool out=(val!=0);\n\t\treturn constGetAction(&out, type, token->getText(), globalNamespace);\n\t}\n\telse\n\t{\n\t\tint out=val;\n\t\treturn constGetAction(&out, type, token->getText(), globalNamespace);\n\t}\n}\n\nAction resolveDubLiteral(Token token)\n{\n\tstring in=token->getText();\n\t\n\tdouble val=0;\n\tint pointPos=0;\n\t\n\tfor (auto i=in.begin(); i!=in.end(); ++i)\n\t{\n\t\tif (*i=='.' || *i=='_')\n\t\t{\n\t\t\tif (pointPos==0)\n\t\t\t{\n\t\t\t\tpointPos=10;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\terror.log(string() + \"multiple decimal points found in number '\" + in + \"'\", SOURCE_ERROR, token);\n\t\t\t\treturn voidAction;\n\t\t\t}\n\t\t}\n\t\telse if (*i>='0' && *i<='9')\n\t\t{\n\t\t\tif (pointPos)\n\t\t\t{\n\t\t\t\tval+=(double)(*i-'0')/pointPos;\n\t\t\t\tpointPos*=10;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tval=val*10+(*i-'0');\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror.log(string() + \"bad character '\" + *i + \"' found in number '\" + in + \"'\", SOURCE_ERROR, token);\n\t\t\treturn voidAction;\n\t\t}\n\t}\n\t\n\tdouble out=val;\n\treturn constGetAction(&out, Dub, token->getText(), globalNamespace);\n}\n\nstring pncnStr2CppStr(void* obj);\nvoid* cppStr2PncnStr(string cpp);\n\nAction resolveStringLiteral(Token token)\n{\n\tstring text=token->getText();\n\t\n\t//this nonesens is required because my lexer is shit and includes the first quote but not the last one\n\t//instead of hardcoding that in, I figured I'd make it flexable so I don't break everthing when I fix the lexer\n\t\n\twhile (text.size()>0 && text[0]=='\"')\n\t\ttext=text.substr(1, string::npos);\n\t\n\twhile (text.size()>0 && text[text.size()-1]=='\"')\n\t\ttext=text.substr(0, text.size()-1);\n\t\n\tvoid* obj=cppStr2PncnStr(text);\n\t\n\treturn constGetAction(obj, String, \"\\\"\"+text+\"\\\"\", globalNamespace);\n}\n\nAction resolveLiteral(Token token)\n{\n\tif (token->getType()==TokenData::STRING_LITERAL)\n\t{\n\t\treturn resolveStringLiteral(token);\n\t}\n\t\n\tif (token->getType()!=TokenData::LITERAL)\n\t{\n\t\tthrow PineconeError(FUNC+\" called on token that is not a literal\", INTERNAL_ERROR, token);\n\t}\n\t\n\tstring in=token->getText();\n\t\n\tif (in.empty())\n\t\treturn nullptr;\n\t\n\t//bool floatingPoint=false;\n\t\n\tType type=Unknown;\n\t\n\tif (in.empty())\n\t{\n\t\terror.log(\"tried to make literal with empty string\", INTERNAL_ERROR, token);\n\t}\n\t\n\tif ((in[0]>='0' && in[0]<='9') || in[0]=='.')\n\t{\n\t\ttype=Int;\n\t\t\n\t\tfor (auto i=in.begin(); i!=in.end(); ++i)\n\t\t{\n\t\t\tif (*i=='.' || *i=='_')\n\t\t\t{\n\t\t\t\ttype=Dub;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (in.back()=='d' || in.back()=='f')\n\t\t{\n\t\t\ttype=Dub;\n\t\t\tin.pop_back();\n\t\t}\n\t\telse if (in.back()=='i')\n\t\t{\n\t\t\ttype=Int;\n\t\t\tin.pop_back();\n\t\t}\n\t\telse if (in.back()=='b')\n\t\t{\n\t\t\ttype=Bool;\n\t\t\tin.pop_back();\n\t\t}\n\t}\n\t\n\tif (type==Int)\n\t{\n\t\treturn resolveIntLiteral(token, type);\n\t}\n\telse if (type==Dub) //floating point\n\t{\n\t\treturn resolveDubLiteral(token);\n\t}\n\telse\n\t{\n\t\tthrow PineconeError(\"tried to make literal with invalid type of \" + type->getString(), INTERNAL_ERROR, token);\n\t}\n}\n\n\n"
  },
  {
    "path": "src/SourceFile.cpp",
    "content": "#include \"../h/SourceFile.h\"\n#include \"../h/utils/fileUtils.h\"\n#include \"../h/msclStringFuncs.h\"\n\nSourceFile::SourceFile(string filenameIn, bool printOutput)\n{\n\tfilename=filenameIn;\n\ttry\n\t{\n\t\tloadFile(filenameIn, contents);\n\t\tcontents+=\"\\n\";\n\t}\n\tcatch (string err)\n\t{\n\t\tthrow PineconeError(err, SOURCE_ERROR);\n\t}\n\t\n}\n\nstring SourceFile::getDirPath()\n{\n\tint i=filename.size();\n\t\n\t// this will break on windows\n\twhile (i>=0 && filename[i]!='/')\n\t{\n\t\ti--;\n\t}\n\t\n\treturn filename.substr(0, i);\n}\n\nstring SourceFile::getBoxedString()\n{\n\treturn str::getBoxedString(contents, filename, true);\n}\n\nstring SourceFile::getLine(int lineNum)\n{\n\treturn getTextOfLine(contents, lineNum);\n}\n"
  },
  {
    "path": "src/StackFrame.cpp",
    "content": "#include \"../h/StackFrame.h\"\n#include \"../h/msclStringFuncs.h\"\n#include \"../h/ErrorHandler.h\"\n\nvoid* globalFramePtr=nullptr;\nvoid* stackPtr=nullptr;\n\nvoid StackFrame::addMember(Type in)\n{\n\tif (!in->isCreatable())\n\t{\n\t\tthrow PineconeError(\"tried to insert uncreatable type \"+in->getString()+\" into stack frame\", INTERNAL_ERROR);\n\t}\n\t\n\tmembers.push_back(in);\n\tframeSize+=in->getSize();\n}\n\nvoid StackFrame::setInput(Type left, Type right)\n{\n\tif (inputSet)\n\t{\n\t\terror.log(\"StackFrame::setInput called multiple times\", INTERNAL_ERROR);\n\t}\n\telse\n\t{\n\t\tif (left->isCreatable())\n\t\t{\n\t\t\tleftInputOffset=frameSize;\n\t\t\tleftInputIndex=members.size();\n\t\t\taddMember(left);\n\t\t}\n\t\telse if (left!=Void)\n\t\t{\n\t\t\tthrow PineconeError(\"stack frame left input set to \"+left->getString()+\", which is neither creatable nore a normal void\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\tif (right->isCreatable())\n\t\t{\n\t\t\trightInputOffset=frameSize;\n\t\t\trightInputIndex=members.size();\n\t\t\taddMember(right);\n\t\t}\n\t\telse if (right!=Void)\n\t\t{\n\t\t\tthrow PineconeError(\"stack frame right input set to \"+right->getString()+\", which is neither creatable nore a normal void\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\tinputSet=true;\n\t}\n}\n\nType StackFrame::getLeftInType()\n{\n\tif (leftInputIndex>=0)\n\t{\n\t\treturn members[leftInputIndex];\n\t}\n\telse\n\t{\n\t\treturn Void;\n\t}\n}\n\nType StackFrame::getRightInType()\n{\n\tif (rightInputIndex>=0)\n\t{\n\t\treturn members[rightInputIndex];\n\t}\n\telse\n\t{\n\t\treturn Void;\n\t}\n}\n\nsize_t StackFrame::getLeftOffset()\n{\n\tif (leftInputIndex>=0)\n\t{\n\t\treturn leftInputOffset;\n\t}\n\telse\n\t{\n\t\terror.log(\"tried to get the left input offset from a stack frame that does not have a left input\", INTERNAL_ERROR);\n\t\treturn 0;\n\t}\n}\n\nsize_t StackFrame::getRightOffset()\n{\n\tif (rightInputIndex>=0)\n\t{\n\t\treturn rightInputOffset;\n\t}\n\telse\n\t{\n\t\tthrow PineconeError(\"tried to get the right input offset from a stack frame that does not have a right input\", INTERNAL_ERROR);\n\t}\n}\n\n"
  },
  {
    "path": "src/Token.cpp",
    "content": "#include \"../h/Token.h\"\n#include \"../h/msclStringFuncs.h\"\n#include \"../h/utils/stringUtils.h\"\n\nToken makeToken(string textIn, shared_ptr<SourceFile> fileIn, int lineIn, int charPosIn, TokenData::Type tokenTypeIn, Operator opIn)\n{\n\tif (str::hasPrefix(textIn, \"\\\"\") && !str::hasSuffix(textIn, \"\\\"\"))\n\t\ttextIn+=\"\\\"\";\n\treturn Token(new TokenData(textIn, fileIn, lineIn, charPosIn, tokenTypeIn, opIn));\n}\n\nToken makeToken(string textIn)\n{\n\treturn Token(new TokenData(textIn, nullptr, 0, 0, TokenData::IDENTIFIER, Operator(nullptr)));\n}\n\nstring TokenData::typeToString(TokenData::Type in)\n{\n\tswitch (in)\n\t{\n\t\tcase WHITESPACE: return \"whitespace\";\n\t\tcase LINE_END: return \"newline\";\n\t\tcase IDENTIFIER: return \"identifier\";\n\t\tcase LITERAL: return \"literal\";\n\t\tcase STRING_LITERAL: return \"string literal\";\n\t\tcase OPERATOR: return \"operator\";\n\t\tcase LINE_COMMENT: return \"single line comment\";\n\t\tcase BLOCK_COMMENT: return \"block comment\";\n\t\tcase SCOPE: return \"scope\";\n\t\tcase UNKNOWN: return \"UNKNOWN\";\n\t\tdefault: return \"ERROR GETTING TOKEN TYPE\";\n\t}\n}\n\nstring TokenData::getDescription()\n{\n\treturn to_string(getLine()) + \":\" + to_string(getCharPos()) + \" (\" + TokenData::typeToString(tokenType) + \" '\" + getText() + \"')\";\n}\n\nstring TokenData::getTypeDescription()\n{\n\tstring out;\n\t\n\tif (tokenType==TokenData::OPERATOR)\n\t{\n\t\tif (op)\n\t\t{\n\t\t\tout+=op->getText()+\" \";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tout+=\"unknown \";\n\t\t}\n\t}\n\t\n\tout+=TokenData::typeToString(tokenType);\n\t\n\treturn out;\n}\n\nstring tableStringFromTokens(const vector<Token>& tokens, string tableName)\n{\n\t/*string out=\"Name\\tType\\n\";\n\t\n\tfor (unsigned i=0; i<tokens.size(); ++i)\n\t{\n\t\tout+=replaceSubstring(tokens[i]->getText(), \"\\n\", \"\\\\n\") + \"\\t\";\n\t\t\n\t\tout+=tokens[i]->getTypeDescription();\n\t\t\n\t\tif (i<tokens.size()-1)\n\t\t\tout+=\"\\n\";\n\t}\n\t\n\treturn putStringInTable(out, tableName);*/\n\t\n\tvector<string> lines;\n\tstring abv=\"\", blw=\"\";\n\tstring str=\"\";\n\t//const int tabSize=1;\n\tconst int maxWidth=240;\n\tconst string seporator=\"    \";\n\t//const string seporator=\"   |   \";\n\t\n\tfor (unsigned i=0; i<tokens.size(); ++i)\n\t{\n\t\t//string next=\" | \";\n\t\t\n\t\t//for (int j=0; j<int(tabSize-str.size()%tabSize); j++)\n\t\t//\tnext+=\" \";\n\t\t\n\t\t//next+=tokens[i]->getText();\n\t\t\n\t\tif (i>0 && str.size()+seporator.size()+tokens[i]->getText().size()<maxWidth)\n\t\t{\n\t\t\tabv+=seporator;\n\t\t\tstr+=seporator;\n\t\t\tblw+=seporator;\n\t\t\t\n\t\t\tfor (unsigned j=0; j<tokens[i]->getText().size(); j++)\n\t\t\t{\n\t\t\t\tabv+=\" \";\n\t\t\t\tblw+=\" \";\n\t\t\t}\n\t\t\t\n\t\t\tstr+=tokens[i]->getText();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (i>0)\n\t\t\t{\n\t\t\t\tlines.push_back(abv);\n\t\t\t\tlines.push_back(str);\n\t\t\t\tlines.push_back(blw);\n\t\t\t\tlines.push_back(\"\");\n\t\t\t\tabv=\"\";\n\t\t\t\tblw=\"\";\n\t\t\t}\n\t\t\t\n\t\t\tfor (unsigned j=0; j<tokens[i]->getText().size(); j++)\n\t\t\t{\n\t\t\t\tabv+=\" \";\n\t\t\t\tblw+=\" \";\n\t\t\t}\n\t\t\t\n\t\t\tstr=tokens[i]->getText();\n\t\t}\n\t}\n\t\n\tlines.push_back(abv);\n\tlines.push_back(str);\n\tlines.push_back(blw);\n\t\n\treturn lineListToBoxedString(lines, tableName, -1, false, maxWidth+4);\n}\n\nstring stringFromTokens(const vector<Token>& tokens, int left, int right)\n{\n\tstring out;\n\t\n\tfor (int i=left; i<=right; ++i)\n\t{\n\t\tout+=tokens[i]->getText();\n\t\tif (i<right)\n\t\t\tout+=\" \";\n\t}\n\t\n\treturn out;\n}\n"
  },
  {
    "path": "src/Type.cpp",
    "content": "#include \"../h/Type.h\"\n#include \"../h/ErrorHandler.h\"\n#include \"../h/CppProgram.h\"\n#include \"../h/msclStringFuncs.h\"\n\n#include <sstream>\n\nusing std::unique_ptr;\nusing std::get;\n\nclass VoidType: public TypeBase\n{\npublic:\n\tvirtual string getString()\n\t{\n\t\treturn \"VOID\";\n\t}\n\t\n\tstring getCompactString()\n\t{\n\t\treturn \"v\";\n\t}\n\t\n\tstring getCppLiteral(void * data, CppProgram * prog)\n\t{\n\t\tthrow PineconeError(\"tried to get the literal value of 'void;\", INTERNAL_ERROR);\n\t}\n\t\n\tbool isCreatable()\n\t{\n\t\treturn false;\n\t}\n\t\n\tbool isVoid()\n\t{\n\t\treturn true;\n\t}\n\t\n\tsize_t getSize()\n\t{\n\t\treturn 0;\n\t}\n\t\n\tPrimitiveType getType()\n\t{\n\t\treturn VOID;\n\t};\n\t\nprotected:\n\t\n\tbool matchesSameTypeType(Type other)\n\t{\n\t\treturn true;\n\t}\n};\n\nclass UnknownType: public TypeBase\n{\npublic:\n\tvirtual string getString()\n\t{\n\t\treturn \"UNKNOWN\";\n\t}\n\t\n\tstring getCompactString()\n\t{\n\t\treturn \"u\";\n\t}\n\t\n\tstring getCppLiteral(void * data, CppProgram * prog)\n\t{\n\t\treturn \"/* can not instantiate unknown type */\";\n\t}\n\t\n\tbool isCreatable()\n\t{\n\t\treturn false;\n\t}\n\t\n\tbool isVoid()\n\t{\n\t\treturn false;\n\t}\n\t\n\tsize_t getSize()\n\t{\n\t\treturn 0;\n\t}\n\t\n\tPrimitiveType getType()\n\t{\n\t\treturn UNKNOWN;\n\t};\n\t\nprotected:\n\t\n\tbool matchesSameTypeType(Type other)\n\t{\n\t\treturn false;\n\t}\n};\n\nclass PrimType: public TypeBase\n{\npublic:\n\t\n\tPrimType(PrimitiveType in)\n\t{\n\t\tprimType=in;\n\t}\n\t\n\tstring getCompactString()\n\t{\n\t\tswitch (primType)\n\t\t{\n\t\t\tcase BOOL: return \"b\";\n\t\t\tcase BYTE: return \"y\";\n\t\t\tcase INT: return \"i\";\n\t\t\tcase DUB: return \"d\";\n\t\t\t\n\t\t\tdefault:\n\t\t\t\tthrow PineconeError(\"tried to make \" + getString() + \" compact\", INTERNAL_ERROR);\n\t\t}\n\t}\n\t\n\tstring getString()\n\t{\n\t\treturn TypeBase::getString(primType);\n\t}\n\t\n\tstring getCppLiteral(void * data, CppProgram * prog)\n\t{\n\t\tstring val;\n\t\t\n\t\tswitch (primType)\n\t\t{\n\t\t\tcase BOOL: val=(*(bool*)data)?\"true\":\"false\"; break;\n\t\t\tcase BYTE: val=to_string(*(unsigned char*)data); break;\n\t\t\tcase INT: val=to_string(*(int*)data); break;\n\t\t\tcase DUB: val=doubleToString(*(double*)data); break;\n\t\t\t/*{\n\t\t\t\tstd::ostringstream ss;\n\t\t\t\tss << *(double*)data;\n\t\t\t\tval=ss.str();\n\t\t\t}\n\t\t\tbreak;*/\n\t\t\t\n\t\t\tdefault:\n\t\t\t\tthrow PineconeError(\"tried to convert \" + getString() + \" to C++ code\", INTERNAL_ERROR);\n\t\t}\n\t\t\n\t\treturn val;\n\t}\n\t\n\tsize_t getSize()\n\t{\n\t\tswitch (primType)\n\t\t{\n\t\t\tcase BOOL: return sizeof(bool);\n\t\t\tcase BYTE: return sizeof(unsigned char);\n\t\t\tcase INT: return sizeof(int);\n\t\t\tcase DUB: return sizeof(double);\n\t\t\t\n\t\t\tdefault:\n\t\t\t\tthrow PineconeError(\"tried to get size of \" + getString(), INTERNAL_ERROR);\n\t\t}\n\t}\n\t\n\tPrimitiveType getType()\n\t{\n\t\treturn primType;\n\t}\n\t\nprotected:\n\t\n\tPrimitiveType primType;\n\t\n\tbool matchesSameTypeType(Type other)\n\t{\n\t\treturn other->getType()==primType;\n\t}\n};\n\nclass TupleType: public TypeBase\n{\npublic:\n\t\n\tTupleType(unique_ptr<vector<NamedType>> in, bool isAnonymousIn)\n\t{\n\t\tif (in==nullptr)\n\t\t\terror.log(FUNC+\" sent null input, compiler will likely shit itself in the near future\", INTERNAL_ERROR);\n\t\t\n\t\tsubTypes=std::move(in);\n\t\t\n\t\tfor (auto i: *subTypes)\n\t\t{\n\t\t\tif (i.type->isWhatev())\n\t\t\t{\n\t\t\t\thasWhatev=true;\n\t\t\t}\n\t\t\t\n\t\t\tif (!i.type->isCreatable())\n\t\t\t{\n\t\t\t\thasOnlyCreatable=false;\n\t\t\t}\n\t\t}\n\t\t\n\t\tisAnonymous=isAnonymousIn;\n\t}\n\t\n\t~TupleType()\n\t{\n\t\t\n\t}\n\t\n\tstring getString()\n\t{\n\t\tstring out;\n\t\t\n\t\tout+=\"{\";\n\t\t\n\t\tfor (int i=0; i<int(subTypes->size()); i++)\n\t\t{\n\t\t\tif (i)\n\t\t\t\tout+=\", \";\n\t\t\t\n\t\t\tout+=(*subTypes)[i].name+\": \"+(*subTypes)[i].type->getString();\n\t\t}\n\t\t\n\t\tout+=\"} (tuple)\";\n\t\t\n\t\treturn out;\n\t}\n\t\n\tstring getCompactString()\n\t{\n\t\tstring out;\n\t\t\n\t\tout+=\"Tt_\";\n\t\t\n\t\tfor (int i=0; i<int(subTypes->size()); i++)\n\t\t{\n\t\t\t//out+=(*subTypes)[i].name.size()+\"_\"+(*subTypes)[i].name+\"_\"+(*subTypes)[i].type->getCompactString()+\"_\";\n\t\t\tout+=(*subTypes)[i].type->getCompactString()+\"_\";\n\t\t}\n\t\t\n\t\tout+=\"tT\";\n\t\t\n\t\treturn out;\n\t}\n\t\n\tstring getCppLiteral(void * data, CppProgram * prog)\n\t{\n\t\tif (subTypes->size()==1)\n\t\t{\n\t\t\treturn (*subTypes)[0].type->getCppLiteral(data, prog);\n\t\t}\n\t\t\n\t\tstring out;\n\t\tout+=prog->getTypeCode(shared_from_this());\n\t\t\n\t\tout+=\"(\";\n\t\t\n\t\tfor (int i=0; i<int(subTypes->size()); i++)\n\t\t{\n\t\t\tif (i)\n\t\t\t\tout+=\", \";\n\t\t\t\n\t\t\tout+=(*subTypes)[i].type->getCppLiteral((char*)data+getSubType((*subTypes)[i].name).offset, prog);\n\t\t}\n\t\t\n\t\tout+=\")\";\n\t\t\n\t\treturn out;\n\t}\n\t\n\tsize_t getSize()\n\t{\n\t\tsize_t sum=0;\n\t\t\n\t\tfor (auto i: *subTypes)\n\t\t{\n\t\t\tsum+=i.type->getSize();\n\t\t}\n\t\t\n\t\treturn sum;\n\t}\n\t\n\tPrimitiveType getType()\n\t{\n\t\treturn TUPLE;\n\t}\n\t\n\tOffsetAndType getSubType(string name)\n\t{\n\t\tsize_t offset=0;\n\t\t\n\t\tfor (auto i: *subTypes)\n\t\t{\n\t\t\tif (i.name==name)\n\t\t\t\treturn {offset, i.type};\n\t\t\telse\n\t\t\t\toffset+=i.type->getSize();\n\t\t}\n\t\t\n\t\treturn {0, nullptr};\n\t}\n\t\n\tvector<NamedType>* getAllSubTypes()\n\t{\n\t\treturn &(*subTypes);\n\t}\n\t\n\tbool isWhatev()\n\t{\n\t\treturn hasWhatev;\n\t}\n\t\n\tbool isCreatable()\n\t{\n\t\treturn hasOnlyCreatable;\n\t}\n\t\n\tType actuallyIs(Type target)\n\t{\n\t\tif (target->getType()!=TUPLE)\n\t\t{\n\t\t\tif ((*subTypes).size()==1)\n\t\t\t{\n\t\t\t\treturn (*subTypes)[0].type->actuallyIs(target);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthrow PineconeError(\"actuallyIs called on tuple with target that is not tuple\", INTERNAL_ERROR);\n\t\t\t}\n\t\t}\n\t\t\n\t\tTupleTypeMaker maker;\n\t\t\n\t\tauto targetTypes=target->getAllSubTypes();\n\t\t\n\t\tfor (int i=0; i<(int)subTypes->size(); i++)\n\t\t{\n\t\t\tmaker.add((*subTypes)[i].name, (*subTypes)[i].type->actuallyIs((*targetTypes)[i].type));\n\t\t}\n\t\t\n\t\treturn maker.get(true);\n\t}\n\t\nprotected:\n\t\n\tbool matchesSameTypeType(Type other)\n\t{\n\t\tauto o=(TupleType*)(&(*other));\n\t\t\n\t\tif (!isAnonymous && !o->isAnonymous)\n\t\t\treturn false;\n\t\t\n\t\tif (subTypes->size()!=o->subTypes->size())\n\t\t\treturn false;\n\t\t\n\t\tfor (int i=0; i<int(subTypes->size()); i++)\n\t\t{\n\t\t\t//if ((*subTypes)[i].name!=(*o->subTypes)[i].name)\n\t\t\t//\treturn false;\n\t\t\t\n\t\t\t//if ((*subTypes)[i].type!=(*o->subTypes)[i].type)\n\t\t\t//\treturn false;\n\t\t\t\n\t\t\tif (!(*subTypes)[i].type->matches((*o->subTypes)[i].type))\n\t\t\t\treturn false;\n\t\t}\n\t\t\n\t\treturn true;\n\t}\n\t\nprivate:\n\t\n\tunique_ptr<vector<NamedType>> subTypes;\n\tbool isAnonymous=true;\n\tbool hasWhatev=false;\n\tbool hasOnlyCreatable=true;\n};\n\nclass PtrType: public TypeBase\n{\npublic:\n\t\n\tPtrType(Type in)\n\t{\n\t\ttype=in;\n\t}\n\t\n\tstring getString()\n\t{\n\t\treturn \"-> \"+type->getString()+\" (pointer)\";\n\t}\n\t\n\tstring getCompactString()\n\t{\n\t\treturn \"Pp_\"+type->getCompactString()+\"_pP\";\n\t}\n\t\n\tstring getCppLiteral(void * data, CppProgram * prog)\n\t{\n\t\tstring name=to_string((long long)data);\n\t\tprog->declareGlobal(name, type, type->getCppLiteral(*(void**)data, prog));\n\t\tstring out=\"&\"+prog->getGlobalNames()->getCpp(name);\n\t\treturn out;\n\t}\n\t\n\tsize_t getSize()\n\t{\n\t\treturn sizeof(void*);\n\t}\n\t\n\tPrimitiveType getType()\n\t{\n\t\treturn PTR;\n\t}\n\t\n\tType getSubType()\n\t{\n\t\treturn type;\n\t}\n\t\n\tType actuallyIs(Type target)\n\t{\n\t\treturn getSubType()->actuallyIs(target->getSubType())->getPtr();\n\t}\n\t\nprotected:\n\t\n\tType type;\n\t\n\tbool matchesSameTypeType(Type other)\n\t{\n\t\treturn ((PtrType*)(&(*other)))->type->matches(type);\n\t}\n};\n\nclass MetaType: public TypeBase\n{\npublic:\n\t\n\tMetaType(Type in)\n\t{\n\t\ttype=in;\n\t}\n\t\n\tstring getString()\n\t{\n\t\treturn \"{\"+type->getString()+\"} (meta type)\";\n\t}\n\t\n\tstring getCompactString()\n\t{\n\t\treturn \"Mm_\"+type->getCompactString()+\"_mM\";\n\t}\n\t\n\tstring getCppLiteral(void * data, CppProgram * prog)\n\t{\n\t\treturn \"/* can't add meta type to C++ code */\";\n\t}\n\t\n\tsize_t getSize()\n\t{\n\t\treturn 0;\n\t}\n\t\n\tbool isCreatable()\n\t{\n\t\treturn false;\n\t}\n\t\n\tPrimitiveType getType()\n\t{\n\t\treturn METATYPE;\n\t}\n\t\n\tType getSubType()\n\t{\n\t\treturn type;\n\t}\n\t\n\tbool isWhatev()\n\t{\n\t\treturn type->isWhatev();\n\t}\n\t\n\tType actuallyIs(Type target)\n\t{\n\t\treturn getSubType()->actuallyIs(target->getSubType())->getMeta();\n\t}\n\t\nprotected:\n\t\n\tType type;\n\t\n\tbool matchesSameTypeType(Type other)\n\t{\n\t\treturn ((MetaType*)(&(*other)))->type==type;\n\t}\n};\n\nclass WhatevType: public TypeBase\n{\npublic:\n\t\n\tWhatevType() {}\n\t\n\tstring getString()\n\t{\n\t\treturn \"(whatev type)\";\n\t}\n\t\n\tstring getCompactString()\n\t{\n\t\treturn \"W\";\n\t}\n\t\n\tbool isCreatable()\n\t{\n\t\treturn false;\n\t}\n\t\n\tstring getCppLiteral(void * data, CppProgram * prog)\n\t{\n\t\tthrow PineconeError(\"getCppLiteral called on whatev type, wich should not have happened\", INTERNAL_ERROR);\n\t}\n\t\n\tsize_t getSize()\n\t{\n\t\tthrow PineconeError(\"getSize called on whatev type, wich should not have happened\", INTERNAL_ERROR);\n\t}\n\t\n\tPrimitiveType getType()\n\t{\n\t\treturn WHATEV;\n\t}\n\t\n\tbool isWhatev()\n\t{\n\t\treturn true;\n\t}\n\t\n\tType getSubType()\n\t{\n\t\tthrow PineconeError(\"getSubType called on whatev type, wich should not have happened\", INTERNAL_ERROR);\n\t}\n\t\n\tType actuallyIs(Type target)\n\t{\n\t\treturn target;\n\t}\n\t\nprotected:\n\t\n\tType type;\n\t\n\tbool matchesSameTypeType(Type other)\n\t{\n\t\treturn true;\n\t}\n};\n\nType TypeBase::makeNewVoid()\n{\n\treturn Type(new VoidType);\n}\n\nType TypeBase::makeNewPrimitive(PrimitiveType typeIn)\n{\n\treturn Type(new PrimType(typeIn));\n}\n\nType TypeBase::makeNewWhatev()\n{\n\treturn Type(new WhatevType());\n}\n\nvector<NamedType>* TypeBase::getAllSubTypes()\n{\n\tthrow PineconeError(\"getAllSubTypes called on type that was not a tuple\", INTERNAL_ERROR);\n}\n\nconst Type Unknown(new UnknownType);\nconst Type Void = TypeBase::makeNewVoid();\nconst Type Whatev = TypeBase::makeNewWhatev();\nconst Type Bool = TypeBase::makeNewPrimitive(TypeBase::BOOL);\nconst Type Byte = TypeBase::makeNewPrimitive(TypeBase::BYTE);\nconst Type Int = TypeBase::makeNewPrimitive(TypeBase::INT);\nconst Type Dub = TypeBase::makeNewPrimitive(TypeBase::DUB);\nType String = nullptr;\n\nType TypeBase::getMeta()\n{\n\treturn Type(new MetaType(shared_from_this()));\n}\n\nType TypeBase::getPtr()\n{\n\tif (!ptrToMe)\n\t\tptrToMe=Type(new PtrType(shared_from_this()));\n\t\n\treturn ptrToMe;\n}\n\nstring TypeBase::getString(PrimitiveType in)\n{\n\tswitch (in)\n\t{\n\t\tcase UNKNOWN: return \"UNKNOWN_TYPE\";\n\t\tcase VOID: return \"VOID\";\n\t\tcase BOOL: return \"BOOL\";\n\t\tcase BYTE: return \"BYTE\";\n\t\tcase INT: return \"INT\";\n\t\tcase DUB: return \"DUB\";\n\t\tcase TUPLE: return \"TUPLE\";\n\t\tcase METATYPE: return \"METATYPE\";\n\t\tdefault: return \"ERROR_GETTING_TYPE\";\n\t}\n}\n\nbool TypeBase::matches(Type other)\n{\n\tif (other==shared_from_this())\n\t\treturn true;\n\t\n\tif (getType()==WHATEV || other->getType()==WHATEV)\n\t\treturn true;\n\t\t\n\tif (getType()==TUPLE)\n\t{\n\t\tauto subTypes=getAllSubTypes();\n\t\t\n\t\tif (subTypes->size()==1)\n\t\t{\n\t\t\tif ((*subTypes)[0].type->matches(other))\n\t\t\t\treturn true;\n\t\t}\n\t}\n\t\n\tif (other->getType()==TUPLE)\n\t{\n\t\tauto subTypes=other->getAllSubTypes();\n\t\t\n\t\tif (subTypes->size()==1)\n\t\t{\n\t\t\tif ((*subTypes)[0].type->matches(shared_from_this()))\n\t\t\t\treturn true;\n\t\t}\n\t}\n\t\n\tif (other->getType()!=getType())\n\t\treturn false;\n\t\n\treturn matchesSameTypeType(other);\n}\n\nType TypeBase::actuallyIs(Type target)\n{\n\tif (!matches(target))\n\t{\n\t\tthrow PineconeError(\"actuallyIs called with type that doesn't match\", INTERNAL_ERROR);\n\t}\n\t\n\tif (isWhatev())\n\t{\n\t\tthrow PineconeError(\"actuallyIs not implemented properly for Whatev type\", INTERNAL_ERROR);\n\t}\n\t\n\treturn shared_from_this();\n}\n\nType makeTuple(const vector<NamedType>& in, bool isAnonymous)\n{\n\tauto ptr=unique_ptr<vector<NamedType>>(new vector<NamedType>(in));\n\treturn Type(new TupleType(move(ptr), isAnonymous));\n}\n\nTupleTypeMaker::TupleTypeMaker()\n{\n\tsubTypes=unique_ptr<vector<NamedType>>(new vector<NamedType>);\n}\n\nvoid TupleTypeMaker::add(string name, Type type)\n{\n\tif (subTypes)\n\t\tsubTypes->push_back(NamedType{name, type});\n\telse\n\t\terror.log(FUNC+\"called after type has been created\", INTERNAL_ERROR);\n}\n\nvoid TupleTypeMaker::add(Type type)\n{\n\tstring name=getUniqueName();\n\t\n\tif (!name.empty())\n\t{\n\t\tadd(name, type);\n\t}\n\telse\n\t{\n\t\terror.log(\"finding unique name in tuple type failed\", INTERNAL_ERROR);\n\t}\n}\n\nType TupleTypeMaker::get(bool isAnonymous)\n{\n\tif (subTypes)\n\t\treturn Type(new TupleType(std::move(subTypes), isAnonymous));\n\telse\n\t\terror.log(FUNC+\"called after type has been created\", INTERNAL_ERROR);\n\t\n\treturn Void;\n}\n\nstring TupleTypeMaker::getUniqueName()\n{\n\tfor (char c='a'; c<='z'; ++c)\n\t{\n\t\tstring str;\n\t\tstr+=c;\n\t\tbool valid=true;\n\t\t\n\t\tfor (auto i: *subTypes)\n\t\t{\n\t\t\tif (i.name==str)\n\t\t\t{\n\t\t\t\tvalid=false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (valid)\n\t\t\treturn str;\n\t}\n\t\n\terror.log(\"you've gotta be fuckin kidding\", SOURCE_ERROR);\n\treturn \"\";\n}\n\n"
  },
  {
    "path": "src/main.cpp",
    "content": "#include \"../h/msclStringFuncs.h\"\n#include \"../h/PineconeProgram.h\"\n#include \"../h/ErrorHandler.h\"\n\n#include <iostream>\n\nusing std::cout;\nusing std::endl;\nusing std::vector;\nusing std::string;\n\nvector <string> cmdLineArgs;\n\nstruct Flags\n{\n\tstring myPath;\t\t\t\t\t// path to the pinecone exeutable that is now running\n\tvector<string> inFiles;\t\t\t// all the input files\n\tbool debug=false;\t\t\t\t// if to show debugging info\n\tbool help=false;\t\t\t\t// if to show help message\n\tbool version=false;\t\t\t\t// if to show version message\n\tbool runInterpreted=true;\t\t// if to run the program in the interpreter\n\tstring cppOutFile=\"\";\t\t\t// output file for transpiled C++ code, empty if flag not set\n\tstring binOutFile=\"\";\t\t\t// binary executable output file, empty if flag not set\n\tbool runCompiled=false;\t\t\t// if to run the program compiled\n\tbool flagError=false;\t\t\t// if to quit immediately, this is set if there is an unrecognised flag\n};\n\nFlags getFlags(int argc, char ** argv);\n\nint main(int argc, char ** argv)\n{\n\tFlags flags=getFlags(argc, argv);\n\t\n\tif (flags.flagError)\n\t{\n\t\tcout << \"try 'pinecone -h' for help\" << endl;\n\t\treturn 0;\n\t}\n\t\n\tif (flags.help)\n\t{\n\t\tcout << \"Pinecone v\" << VERSION_X << \".\" << VERSION_Y << \".\" << VERSION_Z << endl;\n\t\tcout << \"usage: pinecone [options] [source file] [options]\" << endl;\n\t\tcout << \"options: \" << endl;\n\t\tcout << \"-v, -version      display the version of Pinecone\" << endl;\n\t\tcout << \"-d, -debug        display debugging info before running the program\" << endl;\n\t\tcout << \"-r, -run          run the program with the interpreter\" << endl;\n\t\tcout << \"                    active by default if no transpiling commands are present\" << endl;\n\t\tcout << \"                    currently, anything after -r is ignored\" << endl;\n\t\tcout << \"-cpp [file]       transpile to C++ and save the output in the given file\" << endl;\n\t\tcout << \"-bin [file]       transpile, compile with GCC and save the binary\" << endl;\n\t\tcout << \"-e, -execute      transpile, compile and execute the binary\" << endl;\n\t\tcout << \"                    any combination of -cpp, -bin and -e can be used\" << endl;\n\t\tcout << \"                    like -r, anything after -e is ignored\" << endl;\n\t\tcout << \"-h, -help         display this help and quit\" << endl;\n\t\tcout << endl;\n\t\tcout << endl;\n\t\t\n\t\treturn 0;\n\t}\n\t\n\tif (flags.version)\n\t{\n\t\tcout << \"Pinecone version \" << VERSION_X << \".\" << VERSION_Y << \".\" << VERSION_Z << endl;\n\t\treturn 0;\n\t}\n\t\n\tPineconeProgram program;\n\t\n\tif (flags.inFiles.empty())\n\t{\n\t\tcout << \"no source file specified\" << endl;\n\t\tcout << \"try 'pinecone -h' for help\" << endl;\n\t\treturn 0;\n\t}\n\telse if (flags.inFiles.size()>1)\n\t{\n\t\tcout << \"multiple source files specified, Pinecone does not currently support this\" << endl;\n\t\tcout << \"try 'pinecone -h' for help\" << endl;\n\t\treturn 0;\n\t}\n\t\n\tprogram.resolveProgram(flags.inFiles[0], flags.debug);\n\t\n\tif (flags.runInterpreted)\n\t{\n\t\tif (error.getIfErrorLogged())\n\t\t{\n\t\t\tif (flags.debug)\n\t\t\t\tcout << endl << \">>>>>>    execution aborted due to previous error    <<<<<<\" << endl;\n\t\t\telse\n\t\t\t\tcout << \"program not executed due to errors\" << endl;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (flags.debug)\n\t\t\t\tcout << endl << \"running program...\" << endl << endl;\n\t\t\t\n\t\t\tprogram.execute();\n\t\t}\n\t}\n\t\n\tif (!flags.cppOutFile.empty() || !flags.binOutFile.empty() || flags.runCompiled)\n\t{\n\t\tstring cppCode=program.getCpp();\n\t\t\n\t\tif (error.getIfErrorLogged())\n\t\t{\n\t\t\tif (flags.debug)\n\t\t\t\tcout << endl << \">>>>>>    transpiling failed    <<<<<<\" << endl;\n\t\t\telse\n\t\t\t\tcout << \"transpiling failed\" << endl;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstring cppFileName=flags.cppOutFile;\n\t\t\t\n\t\t\tif (cppFileName.empty())\n\t\t\t\tcppFileName=\"tmp_pn_transpiled.cpp\";\n\t\t\t\n\t\t\tif (flags.debug)\n\t\t\t\tcout << endl << putStringInBox(cppCode, \"C++ code\", true, false, -1) << endl;\n\t\t\t\n\t\t\twriteFile(cppFileName, cppCode, flags.debug);\n\t\t\t\n\t\t\tif (!flags.binOutFile.empty() || flags.runCompiled)\n\t\t\t{\n\t\t\t\tstring binFileName=flags.binOutFile;\n\t\t\t\t\n\t\t\t\tif (binFileName.empty())\n\t\t\t\t\tbinFileName=\"tmp_pn_compiled\";\n\t\t\t\t\n\t\t\t\tstring cmd;\n\t\t\t\tcmd=\"g++ -std=c++11 '\"+cppFileName+\"' -o '\"+binFileName+\"'\";\n\t\t\t\t\n\t\t\t\tif (flags.debug)\n\t\t\t\t\tcout << \"running '\"+cmd+\"'\" << endl;\n\t\t\t\t\n\t\t\t\trunCmd(cmd, true);\n\t\t\t\t\n\t\t\t\tif (flags.runCompiled)\n\t\t\t\t{\n\t\t\t\t\tif (flags.debug)\n\t\t\t\t\t\tcout << endl;\n\t\t\t\t\t\n\t\t\t\t\tcmd = \"./\"+binFileName + \" --running-from-pinecone \" + str::join(cmdLineArgs, \" \", false);\n\t\t\t\t\t\n\t\t\t\t\tif (flags.debug)\n\t\t\t\t\t\tcout << \"running '\"+cmd+\"'\" << endl << endl;\n\t\t\t\t\t\n\t\t\t\t\trunCmd(cmd, true);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (flags.binOutFile.empty())\n\t\t\t\t\tremove(binFileName.c_str());\n\t\t\t}\n\t\t\t\n\t\t\tif (flags.cppOutFile.empty())\n\t\t\t\tremove(cppFileName.c_str());\n\t\t}\n\t}\n\t\n\tif (flags.debug)\n\t\tcout << endl << \"all done\" << endl;\n\t\n\treturn 0;\n}\n\nFlags getFlags(int argc, char ** argv)\n{\n\tbool after = false;\n\tFlags flags;\n\t\n\tfor (int i=1; i<argc; i++)\n\t{\n\t\tstring arg(argv[i]);\n\t\tif (!after)\n\t\t{\n\t\t\tif (arg.size()>1 && arg[0]=='-')\n\t\t\t{\n\t\t\t\tstring flag=arg.substr(1, string::npos);\n\n\t\t\t\tif (flag==\"d\" || flag==\"debug\")\n\t\t\t\t{\n\t\t\t\t\tflags.debug=true;\n\t\t\t\t}\n\t\t\t\telse if (flag==\"v\" || flag==\"version\")\n\t\t\t\t{\n\t\t\t\t\tflags.version=true;\n\t\t\t\t}\n\t\t\t\telse if (flag==\"h\" || flag==\"help\")\n\t\t\t\t{\n\t\t\t\t\tflags.help=true;\n\t\t\t\t}\n\t\t\t\telse if (flag==\"r\" || flag==\"run\")\n\t\t\t\t{\n\t\t\t\t\tflags.runCompiled=false;\n\t\t\t\t\tflags.runInterpreted=true;\n\t\t\t\t\tafter = true;\n\t\t\t\t}\n\t\t\t\telse if (flag==\"cpp\")\n\t\t\t\t{\n\t\t\t\t\tif (i+1>=argc)\n\t\t\t\t\t{\n\t\t\t\t\t\tcout << \"output file must follow '-cpp' flag\";\n\t\t\t\t\t\tflags.flagError=true;\n\t\t\t\t\t}\n\n\t\t\t\t\tflags.runInterpreted=false;\n\n\t\t\t\t\tflags.cppOutFile=string(argv[i+1]);\n\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t\telse if (flag==\"bin\")\n\t\t\t\t{\n\t\t\t\t\tif (i+1>=argc)\n\t\t\t\t\t{\n\t\t\t\t\t\tcout << \"output file must follow '-bin' flag\";\n\t\t\t\t\t\tflags.flagError=true;\n\t\t\t\t\t}\n\n\t\t\t\t\tflags.runInterpreted=false;\n\n\t\t\t\t\tflags.binOutFile=string(argv[i+1]);\n\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t\telse if (flag==\"e\" || flag==\"execute\")\n\t\t\t\t{\n\t\t\t\t\tflags.runCompiled=true;\n\t\t\t\t\tflags.runInterpreted=false;\n\t\t\t\t\tafter = true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tcout << \"unknown flag '\"+flag+\"'\" << endl;\n\t\t\t\t\tflags.flagError=true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tflags.inFiles.push_back(arg);\n\t\t\t\tcmdLineArgs.push_back(arg);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tcmdLineArgs.push_back(arg);\n\t\t}\n\t}\n\t\n\treturn flags;\n}\n\n\n"
  },
  {
    "path": "src/msclStringFuncs.cpp",
    "content": "#include \"../h/msclStringFuncs.h\"\n\n#include <fstream>\n#include <sstream>\n#include <unistd.h> // for terminal size detection\n#include <stdlib.h>\n\n//#ifdef _WIN32\n#ifdef __linux__\n//#include <termcap.h>\n#include <sys/ioctl.h> // for terminal size detection\n#endif // __linux__\n\nusing std::stringstream;\n\nbool substringMatches(const string& in, int pos, const string& subStr)\n{\n\t//check if the substring extends past the string size\n\tif (in.size()<pos+subStr.size())\n\t\treturn false;\n\t\n\tfor (unsigned i=0; i<subStr.size(); ++i)\n\t{\n\t\tif (in[i+pos]!=subStr[i])\n\t\t\treturn false;\n\t}\n\t\n\treturn true;\n}\n\nint searchInString(const string& in, const string& pattern, int startPos)\n{\n\tfor (unsigned i=startPos; i<in.size(); i++)\n\t{\n\t\tif (substringMatches(in, i, pattern))\n\t\t\treturn i;\n\t}\n\t\n\treturn -1;\n}\n\nstring replaceSubstring(const string& in, const string& searchFor, const string& replaceWith)\n{\n\tstring out;\n\tint i=0;\n\t\n\twhile (true)\n\t{\n\t\tint j=searchInString(in, searchFor, i);\n\t\t\n\t\tif (j<0)\n\t\t\tbreak;\n\t\telse\n\t\t{\n\t\t\tout+=in.substr(i, j-i);\n\t\t\tout+=replaceWith;\n\t\t\ti=j+searchFor.size();\n\t\t}\n\t}\n\t\n\tout+=in.substr(i, string::npos);\n\t\n\treturn out;\n}\n\nvoid sliceStringBy(const string& in, const string& pattern, vector<string>& out)\n{\n\tint start=0;\n\t\n\tif (pattern.size()<1)\n\t\treturn;\n\t\n\twhile (start<int(in.size()))\n\t{\n\t\tint end=searchInString(in, pattern, start);\n\t\t\n\t\tif (end<0)\n\t\t\tend=in.size();\n\t\t\n\t\tout.push_back(in.substr(start, end-start));\n\t\t\n\t\tstart=end+pattern.size();\n\t}\n}\n\nstring indentString(const string& in, string indent, int level)\n{\n\tstring out;\n\tint start=0;\n\t\n\tfor (int i=0; i<level; i++)\n\t\tout+=indent;\n\t\n\tfor (int i=0; i<int(in.size()-1); i++)\n\t{\n\t\tif (in[i]=='\\n')\n\t\t{\n\t\t\tout+=in.substr(start, i-start+1);\n\t\t\tfor (int i=0; i<level; i++)\n\t\t\t\tout+=indent;\n\t\t\tstart=i+1;\n\t\t}\n\t}\n\t\n\tif (start<=int(in.size()))\n\t\tout+=in.substr(start, in.size()-start);\n\t\n\treturn out;\n}\n\nstring tabsToSpaces(const string& in, int spaceNum)\n{\n\tint xPos=0;\n\tstring out;\n\tint sectionStart=0;\n\t\n\tfor (unsigned i=0; i<in.size(); i++)\n\t{\n\t\tif (substringMatches(in, i, \"\\t\"))\n\t\t{\n\t\t\tstring tabStr;\n\t\t\t\n\t\t\tfor (int j=0; j<spaceNum-(xPos%spaceNum); j++)\n\t\t\t{\n\t\t\t\ttabStr+=\" \";\n\t\t\t}\n\t\t\t\n\t\t\tout+=in.substr(sectionStart, i-sectionStart)+tabStr;\n\t\t\t\n\t\t\tsectionStart=i+1;\n\t\t}\n\t\t\n\t\txPos++;\n\t\t\n\t\tif (substringMatches(in, i, \"\\n\"))\n\t\t{\n\t\t\txPos=0;\n\t\t}\n\t}\n\t\n\tout+=in.substr(sectionStart, in.size());\n\t\n\treturn out;\n}\n\nvoid tabsToSpaces(vector<string>& in)\n{\n\tfor (unsigned i=0; i<in.size(); i++)\n\t{\n\t\tin[i]=tabsToSpaces(in[i]);\n\t}\n}\n\nstring padString(const string& in, int size, int alignment,  string pad, string leftCap, string rightCap)\n{\n\tint capSize=leftCap.size()+rightCap.size();\n\tint padSize=size-int(in.size()+capSize);\n\t\n\tif (padSize<0) // need to chop\n\t{\n\t\tif (size-capSize>=1)\n\t\t{\n\t\t\treturn leftCap+in.substr(0, size-capSize-1)+\"…\"+rightCap;\n\t\t}\n\t\telse if (size-capSize>=0)\n\t\t{\n\t\t\treturn leftCap+string(\"…\").substr(0, size-capSize)+rightCap;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn (leftCap+rightCap).substr(0, size);\n\t\t}\n\t}\n\telse if (padSize==0) // input size was exactly right\n\t{\n\t\treturn leftCap+in+rightCap;\n\t}\n\telse // need to pad\n\t{\n\t\tif (alignment==0) // center alignment\n\t\t{\n\t\t\tstring leftPad, rightPad;\n\t\t\t\n\t\t\tfor (int i=0; i<floor(padSize/2.0); i++)\n\t\t\t\tleftPad+=pad;\n\t\t\t\n\t\t\tfor (int i=0; i<ceil(padSize/2.0); i++)\n\t\t\t\trightPad+=pad;\n\t\t\t\n\t\t\treturn leftPad+leftCap+in+rightCap+rightPad;\n\t\t}\n\t\t// left or right alignment\n\t\telse\n\t\t{\n\t\t\tstring padStr;\n\t\t\t\n\t\t\tfor (int i=0; i<padSize; i++)\n\t\t\t\tpadStr+=pad;\n\t\t\t\n\t\t\tif (alignment>0) // right align\n\t\t\t\treturn leftCap+in+rightCap+padStr;\n\t\t\telse // left align\n\t\t\t\treturn padStr+leftCap+in+rightCap;\n\t\t}\n\n\t}\n}\n\nstring getTextOfLine(const string& in, int lineNum)\n{\n\tint start=-1;\n\tint end=-1;\n\t\n\tif (lineNum<1)\n\t{\n\t\treturn \"\";\n\t}\n\telse if (lineNum==1)\n\t{\n\t\tstart=0;\n\t}\n\t\n\tint line=1;\n\t\n\tfor (unsigned i=0; i<in.size(); i++)\n\t{\n\t\tif (in[i]=='\\n')\n\t\t{\n\t\t\tif (start<0)\n\t\t\t{\n\t\t\t\tline++;\n\t\t\t\t\n\t\t\t\tif (line==lineNum)\n\t\t\t\t{\n\t\t\t\t\tstart=i+1;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tend=i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif (start<end)\n\t\treturn in.substr(start, end-start);\n\telse if (start>=0)\n\t\treturn in.substr(start, string::npos);\n\telse\n\t\treturn \"\";\n}\n\nstring lineListToBoxedString(const vector<string>& in, string boxName, int lineNum, bool alwaysWidthMax, int maxWidth)\n{\n\tstring out;\n\t\n\tauto first=in.begin();\n\tauto last=in.end();\n\t\n\tif (first!=last)\n\t{\n\t\tlast--;\n\t\t\n\t\twhile(first!=last && *first==\"\")\n\t\t{\n\t\t\tfirst++;\n\t\t\tif (lineNum>=0)\n\t\t\t\tlineNum++;\n\t\t}\n\t\t\n\t\twhile (first!=last && *last==\"\")\n\t\t{\n\t\t\tlast--;\n\t\t}\n\t\t\n\t\tlast++;\n\t}\n\t\n\t//the extra width of the padding on the right and left (not the virt lines)\n\tint extraWidth=(lineNum<0)?4:10;\n\t\n\t//the size of the contents (not the container)\n\tint size;\n\t\n\tif (alwaysWidthMax)\n\t{\n\t\tsize=maxWidth-extraWidth;\n\t}\n\telse\n\t{\n\t\tsize=boxName.size()-extraWidth+6;\n\t\t\n\t\tfor (auto i: in)\n\t\t{\n\t\t\tsize=max(size, int(i.size()));\n\t\t}\n\t\t\n\t\tsize=min(maxWidth-extraWidth, size);\n\t}\n\t\n\tif (boxName==\"\")\n\t\tout+=\"  \"+padString(\"\", size+extraWidth, 1, \"_\")+\"  \";\n\telse\n\t\tout+=\"  _\"+padString(boxName, size+extraWidth-2, 0, \"_\", \"[ \", \" ]\")+\"_  \";\n\t\n\tout+=\"\\n |\"+padString(\"\", size+extraWidth, 1, \" \")+\"| \";\n\t\n\tauto i=first;\n\t\n\twhile (i!=last)\n\t{\n\t\tif (lineNum<0)\n\t\t{\n\t\t\tout+=\"\\n |  \";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tout+=\"\\n |\"+padString(to_string(lineNum), 4, -1)+\"    \";\n\t\t\tlineNum++;\n\t\t}\n\t\t\n\t\tout+=padString(*i, size, 1)+\"  | \";\n\t\t\t\n\t\ti++;\n\t}\n\t\n\tout+=\"\\n |\"+padString(\"\", size+extraWidth, 1, \"_\")+\"| \\n\";\n\t\n\treturn out;\n}\n\nstring putStringInBox(const string& in, string boxName, bool showLineNums, bool alwaysWidthMax, int maxWidth)\n{\n\tvector<string> lines;\n\t\n\tif (maxWidth<0)\n\t{\n\t\tmaxWidth=getTermWidth()-4;\n\t}\n\t\n\tsliceStringBy(in, \"\\n\", lines);\n\t\n\ttabsToSpaces(lines);\n\t\n\tstring out=lineListToBoxedString(lines, boxName, showLineNums?1:-1, alwaysWidthMax, maxWidth);\n\t\n\treturn out;\n}\n\nstring putStringInTable(const string& in, string tableName)\n{\n\tvector<string> lineStrs;\n\t\n\tsliceStringBy(in, \"\\n\", lineStrs);\n\t\n\tvector<vector<string>> table;\n\tvector<int> widths;\n\t//vector<string> lines;\n\t\n\tfor (auto i: lineStrs)\n\t{\n\t\tvector<string> row;\n\t\t\n\t\tsliceStringBy(i, \"\\t\", row);\n\t\t\n\t\tfor (unsigned j=0; j<row.size(); j++)\n\t\t{\n\t\t\tif (j==widths.size())\n\t\t\t\twidths.push_back(0);\n\t\t\t\n\t\t\twidths[j]=max(widths[j], int(row[j].size()));\n\t\t}\n\t\t\n\t\ttable.push_back(row);\n\t}\n\t\n\t//make sure each row in the table has the same number of cells\n\tfor (auto i: lineStrs)\n\t{\n\t\tfor (int j=0; j<int(widths.size())-int(table.back().size()); j++)\n\t\t\ttable.back().push_back(\"\");\n\t}\n\t\n\tint totalWidth=0;\n\t\n\tfor (auto i: widths)\n\t\ttotalWidth+=i;\n\t\n\tstring out;\n\t\n\tout+=\"  _\"+padString(tableName, totalWidth+2+(table.back().size()-1)*5, 0, \"_\", \"[ \", \" ]\")+\"_  \";\n\t\n\tfor (auto i: table)\n\t{\n\t\tout+=\"\\n |\";\n\t\t\n\t\tfor (unsigned j=0; j<i.size(); j++)\n\t\t{\n\t\t\tif (j>0)\n\t\t\t\tout+=\"|\";\n\t\t\t\n\t\t\tout+=padString(\"\", widths[j]+4, 1, \" \");\n\t\t}\n\t\t\n\t\t//out+=\"  | \\n |  \"+padString(\"\", totalWidth+(table.back().size()-1)*5, 1, \" \")+\"  | \";\n\t\t\n\t\tout+=\"| \";\n\t\t\n\t\tout+=\"\\n |  \";\n\t\t\n\t\tfor (unsigned j=0; j<i.size(); j++)\n\t\t{\n\t\t\tif (j>0)\n\t\t\t\tout+=\"  |  \";\n\t\t\t\n\t\t\tint alignment=(j==i.size()-1)?(1):((j==0)?(-1):0);\n\t\t\t\n\t\t\tout+=padString(i[j], widths[j], alignment);\n\t\t}\n\t\t\n\t\tout+=\"  | \";\n\t}\n\t\n\tout+=\"\\n |\";\n\t\n\tfor (unsigned j=0; j<table.back().size(); j++)\n\t{\n\t\tif (j>0)\n\t\t\tout+=\"|\";\n\t\t\n\t\tout+=padString(\"\", widths[j]+4, 1, \"_\");\n\t}\n\t\n\tout+=\"| \\n\";\n\t\n\treturn out;\n}\n\nstring doubleToString(double in)\n{\n\tlong long a=in;\n\tlong long b=(in-a)*10000000000;\n\tif (b<0)\n\t\tb*=-1;\n\tif (b%10==9)\n\t\tb+=1;\n\twhile (b>0 && !(b%10))\n\t\tb/=10;\n\treturn to_string(a)+\".\"+to_string(b);\n}\n\nint stringToInt(string in)\n{\n\tint out = 0;\n\t\n\tfor (int i = 0; i < (int)in.size(); i++)\n\t{\n\t\tif (in[i] >= '0' && in[i] <= '9')\n\t\t{\n\t\t\tout = out * 10 + in[i] - '0';\n\t\t}\n\t\telse if (in[i] == '.')\n\t\t\tbreak;\n\t}\n\t\n\tif (in.size() > 0 && in[0] == '-')\n\t\tout *= -1;\n\t\n\treturn out;\n}\n\ndouble stringToDouble(string in)\n{\n\tdouble out = 0;\n\tint divider = 1;\n\t\n\tfor (int i = 0; i < (int)in.size(); i++)\n\t{\n\t\tif (divider == 1)\n\t\t{\n\t\t\tif (in[i] >= '0' && in[i] <= '9')\n\t\t\t\tout = out * 10 + in[i] - '0';\n\t\t\telse if (in[i] == '.')\n\t\t\t\tdivider = 10;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (in[i] >= '0' && in[i] <= '9')\n\t\t\t{\n\t\t\t\tout += (double)(in[i] - '0') / divider;\n\t\t\t\tdivider *= 10;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif (in.size() > 0 && in[0] == '-')\n\t\tout *= -1;\n\t\n\treturn out;\n}\n\nstring loadEntireFile(string inName, bool printOutput)\n{\n\tstd::fstream inFile;\n\t\n\tif (printOutput)\n\t\tcout << \"attempting to open '\" << inName << \"'...\" << endl;\n\t\n\tinFile.open(inName);\n\t\n\tif (!inFile.is_open())\n\t{\n\t\tif (printOutput)\n\t\t\tcout << \"'\" << inName << \"' failed to open :(\" << endl;\n\t\treturn \"\";\n\t}\n\telse\n\t{\n\t\tif (printOutput)\n\t\t\tcout << \"file opended, reading file...\" << endl;\n\t\t\n\t\tstringstream strStream;\n\t\tstrStream << inFile.rdbuf();//read the file\n\t\tstring out = strStream.str();//str holds the content of the file\n\t\tinFile.close();\n\t\t\n\t\tif (printOutput)\n\t\t\tcout << \"file reading done, '\" << inName << \"' closed\" << endl;\n\t\t\n\t\treturn out;\n\t}\n}\n\nbool writeFile(const string& filename, const string& contents, bool debug)\n{\n\tstd::ofstream outFile;\n\t\n\tif (debug)\n\t\tcout << \"attempting to write to '\" << filename << \"'...\" << endl;\n\t\n\toutFile.open(filename);\n\t\n\tif (!outFile.is_open())\n\t{\n\t\tif (debug)\n\t\t\tcout << \"'\" << filename << \"' failed to open :(\" << endl;\n\t\treturn false;\n\t}\n\telse\n\t{\n\t\tif (debug)\n\t\t\tcout << \"file opended, writing to file...\" << endl;\n\t\t\n\t\toutFile << contents;\n\t\t\n\t\toutFile.close();\n\t\t\n\t\tif (debug)\n\t\t\tcout << \"file reading done, '\" << filename << \"' closed\" << endl;\n\t\t\n\t\treturn true;\n\t}\n}\n\n/*\n//NOTE: I copied this from where I copied this from somewhere on the internet. no idea how or why it works.\nstring runCmd(string cmd, bool printOutput) // if print output is false, nothing will be printed unil the entire command is done\n{\n\tconst int bufferSize=4096;\n    char buffer[bufferSize];\n    std::string result = \"\";\n    FILE* pipe = popen(cmd.c_str(), \"r\");\n    if (!pipe) throw std::runtime_error(\"popen() failed in getOutputFromCmd\");\n    try {\n        while (!feof(pipe)) {\n            if (fgets(buffer, bufferSize, pipe) != NULL)\n\t\t\t{\n                result += buffer;\n                if (printOutput)\n\t\t\t\t{\n\t\t\t\t\tcout << buffer;\n\t\t\t\t\tcout.flush();\n\t\t\t\t}\n\t\t\t}\n        }\n    } catch (...) {\n        pclose(pipe);\n        throw;\n    }\n    pclose(pipe);\n    return result;\n}\n*/\n\nchar getRandChar()\n{\n\tstatic unsigned int seed = 1;\n\t//seed = (unsigned)newseed & 0x7fffffffU;\n\t\n\tseed = (seed * 1103515245U + 12345U) & 0x7fffffffU;\n\t\n\tint num=seed%(26+26+10);\n\t\n\tif (num<26)\n\t{\n\t\treturn num+'a';\n\t}\n\telse if (num<26+26)\n\t{\n\t\treturn num-26+'A';\n\t}\n\telse if (num<26+26+10)\n\t{\n\t\treturn num-26-26+'0';\n\t}\n\t\n\treturn '_'; // if I did my arithmetic right, this shouldn't happen\n}\n\nstring getUniqueString(string hint, std::function<bool (string)> checker, bool alwaysAppendRandom)\n{\n\tstring out=hint;\n\t\n\tint attempts=0;\n\tbool invalid=out.empty() || !checker(out) || alwaysAppendRandom;\n\t\n\twhile (invalid)\n\t{\n\t\tif (alwaysAppendRandom || attempts>=10)\n\t\t{\n\t\t\tout=hint+\"_\";\n\t\t\t\n\t\t\tif (attempts>20)\n\t\t\t{\n\t\t\t\tthrow PineconeError(\"could not find unique random name\", INTERNAL_ERROR);\n\t\t\t}\n\t\t\t\n\t\t\tfor (int i=0; i<3; i++)\n\t\t\t\tout+=getRandChar();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstring suffix=to_string(attempts);\n\t\t\t\n\t\t\tout=hint+\"_\"+suffix;\n\t\t}\n\t\tattempts++;\n\t\tinvalid=!checker(out);\n\t}\n\t\n\treturn out;\n}\n\nstring runCmd(string cmd, bool printOutput) // if print output is false, nothing will be printed unil the entire command is done\n{\n    std::string result = \"\";\n    FILE* pipe = popen(cmd.c_str(), \"r\");\n    if (!pipe) throw std::runtime_error(\"popen() failed in getOutputFromCmd\");\n    try {\n        while (!feof(pipe)) {\n\t\t\tchar c;\n            if ((c=getc(pipe)) != EOF)\n\t\t\t{\n                result += c;\n                \n                if (printOutput)\n\t\t\t\t{\n\t\t\t\t\tcout << c;\n\t\t\t\t\tcout.flush();\n\t\t\t\t}\n\t\t\t}\n        }\n    } catch (...) {\n        pclose(pipe);\n        throw;\n    }\n    pclose(pipe);\n    return result;\n}\n\n// TODO: implement for windows\nint getTermWidth()\n{\n\t#ifdef __linux__\n\t\t// reports inacurate size if the terminal is new, as is the case when running from an IDE\n\t\tstatic bool firstTime=true;\n\t\tif (firstTime)\n\t\t{\n\t\t\tusleep(20000);\n\t\t\tfirstTime=false;\n\t\t}\n\t\t\n\t\tstruct winsize w;\n\t\tioctl(STDOUT_FILENO, TIOCGWINSZ, &w);\n\t\t//cout << \"width measured as \" << w.ws_col << endl;\n\t\treturn w.ws_col;\n\t#else\n\t\treturn 80;\n\t#endif\n}\n\n\n"
  },
  {
    "path": "src/utils/fileUtils.cpp",
    "content": "\n#include \"../../h/utils/fileUtils.h\"\n\n#include <fstream>\n#include <sstream>\n\nusing std::stringstream;\n\nvoid loadFile(string filepath, string& contents)\n{\n\tstd::fstream inFile;\n\t\n\tinFile.open(filepath);\n\t\n\tif (!inFile.is_open())\n\t{\n\t\tthrow \"could not open '\"+filepath+\"'\";\n\t}\n\telse\n\t{\n\t\tstringstream strStream;\n\t\tstrStream << inFile.rdbuf();//read the file\n\t\tcontents = strStream.str();//str holds the content of the file\n\t\tinFile.close();\n\t}\n}\n\nvoid writeFile(string filepath, const string& contents)\n{\n\tstd::ofstream outFile;\n\t\n\toutFile.open(filepath);\n\t\n\tif (!outFile.is_open())\n\t{\n\t\tthrow \"error writing to '\"+filepath+\"'\";\n\t}\n\telse\n\t{\n\t\toutFile << contents;\n\t\t\n\t\toutFile.close();\n\t}\n}\n\n"
  },
  {
    "path": "src/utils/stringArray.cpp",
    "content": "#include \"../../h/utils/stringArray.h\"\n\nnamespace str\n{\n\nint getMaxWidth(vector<string>& in)\n{\n\tint out=0;\n\t\n\tfor (int i=0; i<(int)in.size(); i++)\n\t{\n\t\tint w=getWidth(in[i]);\n\t\t\n\t\tif (w>out)\n\t\t\tout=w;\n\t}\n\t\n\treturn out;\n}\n\nvoid padWidths(vector<string>& out, int size, StringPadAlignment alignment, string pad, string leftCap, string rightCap)\n{\n\tif (size<0)\n\t{\n\t\tsize=getMaxWidth(out);\n\t}\n\t\n\tfor (int i=0; i<(int)out.size(); i++)\n\t{\n\t\tout[i]=str::pad(out[i], size, alignment, pad, leftCap, rightCap);\n\t}\n}\n\nstring join(vector<string>& in, string joiner, bool addAtEnd)\n{\n\tstring out;\n\t\n\tfor (int i=0; i<(int)in.size(); i++)\n\t{\n\t\tout+=in[i];\n\t\t\n\t\tif (addAtEnd || i!=(int)in.size()-1)\n\t\t\tout+=joiner;\n\t}\n\t\n\treturn out;\n}\n\n\n}\n\n\n"
  },
  {
    "path": "src/utils/stringDrawing.cpp",
    "content": "\n#include \"../../h/utils/stringDrawing.h\"\n#include \"../../h/utils/stringArray.h\"\n\n#include \"../../h/msclStringFuncs.h\"\n\n//#include <math.h>\n\nnamespace str\n{\n\n// https://en.wikipedia.org/wiki/Box-drawing_character\n// │ ─ ╭ ╮ ╯ ╰\n\nstring getBoxedString(const string& in, string boxName, bool showLineNums, bool alwaysWidthMax, int maxWidth)\n{\n\tvector<string> lines;\n\tint width;\n\t\n\tif (maxWidth<0)\n\t{\n\t\tmaxWidth=getTermWidth()-4;\n\t}\n\t\n\tstr::splitByLine(lines, tabsToSpaces(in));\n\t\n\tint startLineNum=1;\n\t\n\twhile (!lines.empty() && lines[0].empty())\n\t{\n\t\tlines.erase(lines.begin());\n\t\tstartLineNum++;\n\t}\n\t\n\twhile (!lines.empty() && lines.back().empty())\n\t{\n\t\tlines.pop_back();\n\t}\n\t\n\tint nameWidth=getWidth(boxName);\n\t\n\tif (showLineNums)\n\t{\n\t\tint numChars=getWidth(to_string(lines.size()+startLineNum-1));\n\t\t\n\t\tfor (int i=0; i<(int)lines.size(); i++)\n\t\t{\n\t\t\tlines[i]=pad(to_string(i+startLineNum), numChars+5, ALIGNMENT_RIGHT, \" \", \"\", \"    \")+lines[i];\n\t\t}\n\t}\n\t\n\tif (alwaysWidthMax)\n\t{\n\t\twidth=maxWidth;\n\t}\n\telse\n\t{\n\t\twidth=std::min(std::max(str::getMaxWidth(lines), nameWidth+4-2), maxWidth);\n\t}\n\t\n\tstr::padWidths(lines, width);\n\t\n\tfor (int i=0; i<(int)lines.size(); i++)\n\t{\n\t\tlines[i]=\" ┃ \"+lines[i]+\" ┃ \";\n\t}\n\t\n\tstring bottom;\n\tstring emptyLn;\n\t\n\tfor (int i=0; i<width; i++)\n\t{\n\t\tbottom+=\"━\";\n\t\temptyLn+=\" \";\n\t}\n\t\n\tif (boxName.empty())\n\t{\n\t\tlines.insert(lines.begin(), \" ┃ \"+bottom+ \" ┃ \");\n\t\tlines.insert(lines.begin(), \" ┏━\"+emptyLn+\"━┓ \");\n\t}\n\telse\n\t{\n\t\tstring underline;\n\t\tfor (int i=0; i<nameWidth; i++)\n\t\t{\n\t\t\tunderline+=\"─\";\n\t\t}\n\t\t\n\t\tlines.insert(lines.begin(), \" ┃\"+pad(underline,\twidth+2, ALIGNMENT_CENTER, \" \", \"╰─\", \"─╯\")+\"┃ \");\n\t\tlines.insert(lines.begin(), \" ┏\"+pad(boxName,\twidth+2, ALIGNMENT_CENTER, \"━\", \"┥ \", \" ┝\")+\"┓ \");\n\t\tlines.insert(lines.begin(), \"  \"+pad(underline,\twidth+2, ALIGNMENT_CENTER, \" \", \"╭─\", \"─╮\")+\"  \");\n\t}\n\t\n\t\n\tlines.push_back(\" ┃ \"+emptyLn+\" ┃ \");\n\tlines.push_back(\" ┗━\"+bottom +\"━┛ \");\n\t\n\t\n\t\n\treturn join(lines);\n}\n\n/*\nstring makeTreeSection(const string& root, vector<string>& leaves)\n{\n\treturn \"makeTreeSection not yet implemented\";\n}\n*/\n\nvoid putArrayInTreeNodeBox(vector<string>& data)\n{\n\tint width=data.empty()?0:getWidth(data[0]);\n\t\n\tfor (int i=0; i<(int)data.size(); i++)\n\t{\n\t\tdata[i]=\"│ \"+data[i]+\" │\";\n\t}\n\t\n\tdata.push_back(\"╰─\"+pad(\"\", width, ALIGNMENT_LEFT, \"─\")+\"─╯\");\n\tdata.insert(data.begin(), \"╭─\"+pad(\"┴\", width, ALIGNMENT_CENTER, \"─\")+\"─╮\");\n}\n\nstring putStringInTreeNodeBox(const string& in)\n{\n\tvector<string> ary;\n\tsplitByLine(ary, in);\n\tputArrayInTreeNodeBox(ary);\n\treturn join(ary);\n}\n\nstring makeList(vector<string>& data)\n{\n\tvector<string> ary;\n\t\n\tfor (int i=0; i<int(data.size()); i++)\n\t{\n\t\tvector<string> elemAry;\n\t\tstr::splitByLine(elemAry, data[i]);\n\t\tint xPos=str::getGlyphPosOf(elemAry[0], \"┴\");\n\t\tif (xPos>=0)\n\t\t{\n\t\t\tary.push_back(\"┠─\"+str::pad(\"\", xPos, str::ALIGNMENT_LEFT, \"─\")+\"╮\");\n\t\t}\n\t\tfor (auto i: elemAry)\n\t\t{\n\t\t\tary.push_back(\"┃ \"+i);\n\t\t}\n\t}\n\t\n\tpadWidths(ary);\n\t\n\tfor (int i=0; i<int(ary.size()); i++)\n\t{\n\t\tary[i]=ary[i]+\" ┃\";\n\t}\n\t\n\tint width=str::getMaxWidth(ary);\n\t\n\tary.insert(ary.begin(), \"┏━┴\"+padString(\"\", width-4, str::ALIGNMENT_LEFT, \"━\")+\"┓\");\n\tary.push_back(\"┗\"+padString(\"\", width-2, str::ALIGNMENT_LEFT, \"━\")+\"┛\");\n\t\n\treturn str::join(ary);\n}\n\nstring makeRootUpBinaryTree(const string& root, const string& leftBranch, const string& rightBranch, const string& leftLeaf, const string& rightLeaf)\n{\n\tvector<string> leftAry;\n\tsplitByLine(leftAry, leftLeaf);\n\t\n\tvector<string> rightAry;\n\tsplitByLine(rightAry, rightLeaf);\n\t\n\t/*\n\tif (rightAry.empty() && !leftAry.empty())\n\t\trightAry.push_back(padString(\"\", getMaxWidth(leftAry)));\n\t\n\tif (leftAry.empty() && !rightAry.empty())\n\t\tleftAry.push_back(padString(\"\", getMaxWidth(rightAry)));\n\t\t\n\tif (leftAry.empty())\n\t\tleftAry.push_back(\"\");\n\t*/\n\t\n\t// make sure left and right arrays are the same size\n\twhile (leftAry.size()<rightAry.size())\n\t\tleftAry.push_back(\"\");\n\twhile (rightAry.size()<leftAry.size())\n\t\trightAry.push_back(\"\");\n\t\n\t// set up the root array\n\tvector<string> rootAry;\n\tsplitByLine(rootAry, root);\n\tif (rootAry.empty())\n\t\trootAry.push_back(\"\");\n\tpadWidths(rootAry);\n\t\n\tint rootWidth=getMaxWidth(rootAry);\n\t//int leafWidth=std::max(std::max(getMaxWidth(leftAry), getMaxWidth(rightAry)), rootWidth)+1;\n\t\n\t//padWidths(leftAry, leafWidth, ALIGNMENT_LEFT);\n\t//padWidths(rightAry, leafWidth, ALIGNMENT_RIGHT);\n\t\n\t// make sure everything is padded\n\tpadWidths(leftAry);\n\tpadWidths(rightAry);\n\t\n\t//int size=std::max(rootWidth, getMaxWidth(leftAry)+getMaxWidth(rightAry));\n\t\n\tint leftPadWidth=0;\n\t\n\t// left connection line\n\tif (!leftLeaf.empty())\n\t{\n\t\tint endXPos=getGlyphPosOf(leftAry[0], \"┴\");\n\t\tint leftBranchWidth=getWidth(leftBranch);\n\t\tif (endXPos>0)\n\t\t{\n\t\t\tint leftMargin=0;//(getMaxWidth(leftAry)-leftBranchWidth)/2;\n\t\t\tif (leftMargin>0)\n\t\t\t{\n\t\t\t\tfor (int i=0; i<(int)leftAry.size(); i++)\n\t\t\t\t{\n\t\t\t\t\tleftAry[i]=pad(\"\", leftMargin)+leftAry[i];\n\t\t\t\t}\n\t\t\t\tendXPos+=leftMargin;\n\t\t\t}\n\t\t\tint middleYPos=rootAry.size()/2;\n\t\t\trootAry[middleYPos]=\"┤\"+sub(rootAry[middleYPos], 1, -1);\n\t\t\tleftPadWidth=getMaxWidth(leftAry)-rootWidth/2;\n\t\t\tif (endXPos+1>leftPadWidth)\n\t\t\t\tleftPadWidth=endXPos+1;\n\t\t\tleftPadWidth=max(leftPadWidth, (int)ceil(leftBranchWidth/2.0)+endXPos);\n\t\t\tfor (int i=0; i<(int)rootAry.size(); i++)\n\t\t\t{\n\t\t\t\tif (i<middleYPos)\n\t\t\t\t\trootAry[i]=padString(\"\", leftPadWidth)+rootAry[i];\n\t\t\t\telse if (i==middleYPos)\n\t\t\t\t\trootAry[i]=padString(\"\", endXPos)+\"╭\"+padString(\"\", leftPadWidth-endXPos-1, ALIGNMENT_LEFT, \"─\")+rootAry[i];\n\t\t\t\telse if (i==middleYPos+1 && !leftBranch.empty())\n\t\t\t\t{\n\t\t\t\t\trootAry[i]=padString(\"\", endXPos-floor(leftBranchWidth/2.0))+leftBranch+padString(\"\", leftPadWidth-endXPos-ceil(leftBranchWidth/2.0))+rootAry[i];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\trootAry[i]=padString(\"\", endXPos)+\"│\"+padString(\"\", leftPadWidth-endXPos-1)+rootAry[i];\n\t\t\t}\n\t\t}\n\t}\n\t\n\t// right connection line\n\tif (!rightLeaf.empty())\n\t{\n\t\tint endXPos=getGlyphPosOf(rightAry[0], \"┴\");\n\t\tint rightBranchWidth=getWidth(rightBranch);\n\t\tif (endXPos>0)\n\t\t{\n\t\t\tint middleYPos=rootAry.size()/2;\n\t\t\trootAry[middleYPos]=sub(rootAry[middleYPos], 0, getWidth(rootAry[middleYPos])-1)+\"├\";\n\t\t\tint inset=rootWidth/2;\n\t\t\tinset=min(endXPos-(int)floor(rightBranchWidth/2.0), inset);\n\t\t\tfor (int i=0; i<(int)rootAry.size(); i++)\n\t\t\t{\n\t\t\t\tif (i<middleYPos)\n\t\t\t\t\trootAry[i]=rootAry[i]+padString(\"\", getMaxWidth(rightAry)-inset);\n\t\t\t\telse if (i==middleYPos)\n\t\t\t\t\trootAry[i]=rootAry[i]+padString(\"\", endXPos-inset, ALIGNMENT_LEFT, \"─\")+\"╮\";\n\t\t\t\telse if (i==middleYPos+1 && !rightBranch.empty())\n\t\t\t\t\trootAry[i]=rootAry[i]+pad(\"\", endXPos-inset-floor(rightBranchWidth/2.0))+rightBranch;\n\t\t\t\telse\n\t\t\t\t\trootAry[i]=rootAry[i]+padString(\"\", endXPos-inset)+\"│\";\n\t\t\t}\n\t\t\t\n\t\t\tfor (int i=0; i<(int)leftAry.size(); i++)\n\t\t\t{\n\t\t\t\tleftAry[i]=leftAry[i]+pad(\"\", rootWidth+leftPadWidth-getWidth(leftAry[i])-inset);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tfor (int i=0; i<(int)leftAry.size(); i++)\n\t{\n\t\trootAry.push_back(leftAry[i]+rightAry[i]);\n\t}\n\t\n\tpadWidths(rootAry);\n\t\n\treturn join(rootAry);\n}\n\n}\n\n"
  },
  {
    "path": "src/utils/stringNumConversion.cpp",
    "content": "#include \"../../h/utils/stringNumConversion.h\"\n#include <cstring> // for memcpy\n\nnamespace str\n{\n\nstring charToCppStringLiteralEscaped(unsigned char c)\n{\n\tstring out=\"\\\\\";\n\t\n\tfor (int i=0; i<3; i++)\n\t{\n\t\tout+=c%8+'0';\n\t\tc/=8;\n\t}\n\t\n\treturn out;\n}\n\nstring intToBase62(unsigned int num, int maxDigits)\n{\n\tint i=0;\n\tstring out;\n\t\n\twhile (num!=0 && (maxDigits<0 || i<maxDigits))\n\t{\n\t\tunsigned int digit=num%62;\n\t\t\n\t\tif (digit<10)\n\t\t{\n\t\t\tout+=(char)(digit+'0');\n\t\t}\n\t\telse if (digit<10+26)\n\t\t{\n\t\t\tout+=(char)(digit-10+'a');\n\t\t}\n\t\telse if (digit<10+26+26)\n\t\t{\n\t\t\tout+=(char)(digit-10-26+'A');\n\t\t}\n\t\telse\n\t\t{\n\t\t\tout+=\"_\"; // this shouldn't happen\n\t\t}\n\t\t\n\t\tnum/=62;\n\t\ti++;\n\t}\n\t\n\treturn out;\n}\n\nstring ptrToUniqueStr(void* ptrIn, int digits)\n{\n\tunsigned long long data=0;\n\tmemcpy(&data, &ptrIn, sizeof(void*));\n\treturn intToBase62((int)data, digits);\n}\n\n}\n\n"
  },
  {
    "path": "src/utils/stringUtils.cpp",
    "content": "#include \"../../h/utils/stringUtils.h\"\n#include <math.h>\n\nnamespace str\n{\n\nvoid splitBy(vector<string>& out, const string& in, const string& splitter, bool keepSplitter)\n{\n\tint i=0;\n\tint start=0;\n\t\n\twhile (i<=(int)in.size()-(int)splitter.size())\n\t{\n\t\tif (subMatches(in, i, splitter))\n\t\t{\n\t\t\tif (keepSplitter)\n\t\t\t\tnextGlyph(i, in);\n\t\t\t\n\t\t\tout.push_back(in.substr(start, i-start));\n\t\t\t\n\t\t\tif (!keepSplitter)\n\t\t\t\tnextGlyph(i, in);\n\t\t\t\n\t\t\tstart=i;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tnextGlyph(i, in);\n\t\t}\n\t}\n\t\n\tif ((int)in.size()!=start)\n\t\tout.push_back(in.substr(start, in.size()-start));\n}\n\nstring pad(const string& in, int size, StringPadAlignment alignment, string pad, string leftCap, string rightCap)\n{\n\tint capWidth=getWidth(leftCap)+getWidth(rightCap);\n\tint inSize=getWidth(in);\n\tint padSize=size-(inSize+capWidth);\n\t\n\tif (padSize<0) // need to chop\n\t{\n\t\tif (size-capWidth>=1)\n\t\t{\n\t\t\tif (alignment==ALIGNMENT_RIGHT)\n\t\t\t{\n\t\t\t\treturn leftCap+\"…\"+sub(in, inSize-(size-capWidth-1), inSize)+rightCap;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn leftCap+sub(in, 0, size-capWidth-1)+\"…\"+rightCap;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn sub(leftCap+rightCap, 0, size);\n\t\t}\n\t}\n\telse if (padSize==0) // input size was exactly right\n\t{\n\t\treturn leftCap+in+rightCap;\n\t}\n\telse // need to pad\n\t{\n\t\tif (alignment==ALIGNMENT_CENTER) // center alignment\n\t\t{\n\t\t\tstring leftPad, rightPad;\n\t\t\t\n\t\t\tfor (int i=0; i<floor(padSize/2.0); i++)\n\t\t\t\tleftPad+=pad;\n\t\t\t\n\t\t\tfor (int i=0; i<ceil(padSize/2.0); i++)\n\t\t\t\trightPad+=pad;\n\t\t\t\n\t\t\treturn leftPad+leftCap+in+rightCap+rightPad;\n\t\t}\n\t\t// left or right alignment\n\t\telse\n\t\t{\n\t\t\tstring padStr;\n\t\t\t\n\t\t\tfor (int i=0; i<padSize; i++)\n\t\t\t\tpadStr+=pad;\n\t\t\t\n\t\t\tif (alignment==ALIGNMENT_RIGHT) // right align\n\t\t\t\treturn padStr+leftCap+in+rightCap;\n\t\t\telse // left align\n\t\t\t\treturn leftCap+in+rightCap+padStr;\n\t\t}\n\t}\n}\n\nstring tabsToSpaces(const string& in, int tabWidth)\n{\n\tint widthSinceNewline=0;\n\tstring out;\n\tint bytePos=0;\n\tint start=0;\n\t\n\twhile (bytePos<(int)in.size())\n\t{\n\t\tif (subMatches(in, bytePos, \"\\t\"))\n\t\t{\n\t\t\tout+=in.substr(start, bytePos-start);\n\t\t\tstring spacer;\n\t\t\tint spaces=tabWidth-(widthSinceNewline%tabWidth);\n\t\t\tfor (int i=0; i<spaces; i++)\n\t\t\t\tspacer+=\" \";\n\t\t\tout+=spacer;\n\t\t\twidthSinceNewline+=spaces;\n\t\t\tnextGlyph(bytePos, in);\n\t\t\tstart=bytePos;\n\t\t}\n\t\telse\n\t\t{\n\t\t\twidthSinceNewline++;\n\t\t\tif (subMatches(in, bytePos, \"\\n\"))\n\t\t\t{\n\t\t\t\twidthSinceNewline=0;\n\t\t\t}\n\t\t\tnextGlyph(bytePos, in);\n\t\t}\n\t}\n\t\n\tout+=in.substr(start, bytePos-start);\n\t\n\treturn out;\n}\n\nint getGlyphPosOf(const string& in, string pattern)\n{\n\tint glyph=0;\n\tint byte=0;\n\t\n\twhile (byte<(int)in.size())\n\t{\n\t\tif (subMatches(in, byte, pattern))\n\t\t\treturn glyph;\n\t\t\n\t\tnextGlyph(byte, in);\n\t\tglyph++;\n\t}\n\t\n\treturn -1;\n}\n\n}\n\n\n"
  },
  {
    "path": "tests/integration/brainfuck.pn",
    "content": "# Tests the Pinecone brainfuck interpreter\n\n# for the interpreter to be happy, there needs to be an extra newline at the end, idk why\nprint: \"enter your brainfuck code: Hello World!\\n\\n_____\"\n\nsymInput: \"++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.\"\n\noptions: \"\"\n\nIS_TRANSPILED ?\n\toptions: options+\" -e\"\n\ncmdOut: runCmd: \"printf '\"+symInput+\"' | ./pinecone examples/brainfuck.pn\" + options\n\nprint: cmdOut\n\n"
  },
  {
    "path": "tests/integration/morse.pn",
    "content": "# Tests my text to morse code converter\n\nprint: \"enter some text or type quit: .--. .. -. . -.-. --- -. . \\nenter some text or type quit: .-.. .- -. --. \\nenter some text or type quit: \\n\\n_____\"\n\nsymInput: \"pinecone\\\\nlang\\\\nquit\"\n\noptions: \"\"\n\nIS_TRANSPILED ?\n\toptions: options+\" -e\"\n\ncmd: \"printf '\"+symInput+\"' | ./pinecone examples/morse.pn\" + options\n\nprint: runCmd: cmd\n\n"
  },
  {
    "path": "tests/integration/queue.pn",
    "content": "# this is a copy of the original file used for an intagration test\n# this is an implementation of a queue using a dynamically sized circular buffer\n# this was wretten for Pinecone v0.3, which does not yet have references, so a single global queue is used instead of a queue object\n\nprint: \"1\\n2\\n3\\n4\\n5\\n6\\nqueue {\\n    7\\n    8\\n    9\\n}\\n\\n_____\"\n\nq: Queue\nmain\n\nmain :: {}:\n(\n\tenqueue: 1\n\tenqueue: 2\n\tenqueue: 3\n\tenqueue: 4\n\tenqueue: 5\n\tenqueue: 6\n\t\n\tprint: dequeue\n\tprint: dequeue\n\tprint: dequeue\n\tprint: dequeue\n\t\n\tenqueue: 7\n\tenqueue: 8\n\tenqueue: 9\n\t\n\tprint: dequeue\n\tprint: dequeue\n\t\n\tprint: q\n)\n\nQueue :: {array: IntArray, offset: Int, len: Int}\n\nQueue :: {} -> {Queue}: (\n\t(IntArray: 1), 0, 0\n)\n\nresize :: {Int}: (\n\t\n\tnewArray: IntArray: in\n\t\n\ti: 0 | i<q.len | i: i+1 @ (\n\t\ttmp: q.array\n\t\tnewArray.set: i, (tmp.get: (i+q.offset)%q.array.len)\n\t)\n\t\n\tq: newArray, 0, q.len\n)\n\nenqueue :: {Int}: (\n\t\n\tq.len >= q.array.len ?\n\t\tresize: q.array.len*2\n\t\n\tq: q.array, q.offset, q.len+1\n\t\n\ttmp: q.array\n\ttmp.set: (q.offset+q.len-1)%q.array.len, in\n)\n\ndequeue :: {} -> {Int}: (\n\t\n\ttmp: q.array\n\tout: tmp.get: q.offset%q.array.len\n\tq: q.array, q.offset+1, q.len-1\n\t\n\tq.len < q.array.len/3+1 ?\n\t\tresize: q.array.len/3+1\n\t\n\tout\n)\n\npeek :: {}: (\n\ttmp: q.array\n\ttmp.get: q.offset%q.array.len\n)\n\nprint :: {Queue}: (\n\t\n\tprint: \"queue {\"\n\ti: 0 | i<in.len | i: i+1 @ (\n\t\t#Bool: i ?\n\t\t#\tprint: \", \"\n\t\tary: in.array\n\t\tprint: \"    \"+(ary.get: (i+in.offset)%in.array.len).String\n\t)\n\tprint: \"}\"\n\tprint\n\t\n\t//\n\tprint: \"raw array {\"\n\ti: 0 | i<in.array.len | i: i+1 @ (\n\t\t#Bool: i ?\n\t\t#\tprint: \", \"\n\t\tary: in.array\n\t\tout: (ary.get: i).String\n\t\ti = in.offset ?\n\t\t\tout: \" -> \"+out\n\t\t| i = (in.offset+in.len-1)%in.array.len ?\n\t\t\tout: \" -| \"+out\n\t\t|\n\t\t\tout: \"    \"+out\n\t\tprint: out\n\t)\n\tprint: \"}\"\n\tprint\n\t\\\\\n)\n\n\n\n"
  },
  {
    "path": "tests/readme.md",
    "content": "This directory holds all tests for the Pinecone language. To run tests, open the parent directory in terminal and run\n`./pinecone tests/run_tests.pn`. It is important that your current working directory is the parent directory and that there is a pinecone executable in the parent directory called `pinecone`.\n"
  },
  {
    "path": "tests/regression/bool_short_circuit.pn",
    "content": "# Tests if short circuit is applied to operations with multiple bools\n\nprint: \"1\\nmyFunc called\\nmyFunc called\\nmyFunc called\\nmyFunc called\\n4\\n_____\"\n\ntru || (myFunc: tru) ?\n\tprint: 1\n\nfls && (myFunc: tru) ?\n\tprint: 2\n\n!(myFunc: tru) || fls ?\n\tprint: 3\n\n(myFunc: fls) || (myFunc: fls) || (myFunc: tru) || (myFunc: fls) ?\n\tprint: 4\n\nmyFunc :: {Bool} -> {Bool}: (\n\tprint: \"myFunc called\"\n\tin\n)\n\n"
  },
  {
    "path": "tests/regression/cpp_bad_escape_seq.pn",
    "content": "# Bad escape sequences can get into C++ transpiled code if a special char is followed by a hex digit\n\ntab: \"\\t\"\n\nprint: tab + \"axyz\\n_____\"\n\nprint: \"\\taxyz\"\n\n\n"
  },
  {
    "path": "tests/regression/cpp_global_and_local_same_name.pn",
    "content": "# it gets confused when global and local vars have the same name\n\nprint: \"3\\n3\\n_____\"\n\na: 7\n\nfunc :: {a: Int, b: Int}: (\n\t\n\ta: in.a\n\t\n\tprint: a\n)\n\nfunc: 3, 3\n\nprint: a\n\n"
  },
  {
    "path": "tests/regression/error_on_nonexistant_file.pn",
    "content": "# This test attempts to run the Pinecone interpreter on a nonexistant file, which should produce an error\n\nprint: \"error: could not open 'thisFileDoesNotExist.pn'\\nprogram not executed due to errors\\n\\n_____\"\n\ncmd: \"./pinecone thisFileDoesNotExist.pn\"\n\noutput: runCmd: cmd\n\nprint: output\n\n"
  },
  {
    "path": "tests/regression/function_with_one_named_arg.pn",
    "content": "# test when there is a function that only has one argument which is named\n\nprint: \"8\\n_____\"\n\nmyFunc: 8\n\nmyFunc :: {arg: Int}: (\n\t\n\tprint: in.arg\n)\n\n"
  },
  {
    "path": "tests/regression/if_as_ternary.pn",
    "content": "# tests the if statement as a ternary operator, I think problem is if return type may always be void\n\nprint: \"yes\\n_____\"\n\na: tru\nprint: (a ? \"yes\" | \"no\")\n\n"
  },
  {
    "path": "tests/regression/multiple_left_inputs.pn",
    "content": "# tests when there are multiple left inputs to a function\n# original but was caused to failing to skip {} in parsing an a.b: c structure\n\nprint: \"7\\ntru\\n_____\"\n\n\nfunc :: {Int, Bool}.{}: (\n\tprint: me.a\n\tprint: me.b\n)\n\n(7, tru).func\n\n"
  },
  {
    "path": "tests/regression/negative_literal.pn",
    "content": "# this tests negitive literal numbers \n\nprint: \"-3\\n-4.7\\n9\\n_____\"\n\nprint: -3\nprint: -4.7\nprint: 7-(-2)\n"
  },
  {
    "path": "tests/regression/no_newline_at_end.pn",
    "content": "# Pinecone test for source file without newline at the end of the file\n# IMPORTANT: many editors will automatically insert a newline on save, so don't edit this file unless you know what you're doing\nprint: \"es\\n_____\"\n\na: \"test\"\nprint: a.sub: 1, 3"
  },
  {
    "path": "tests/run_tests.pn",
    "content": "\npthslsh: \"/\"\n\nOS_IS_WINDOWS ?\n\tpthslsh: \"\\\\\"\n\nerrorDetails: String\n\nprint: \"pinecone v\"+VERSION.x.String+\".\"+VERSION.y.String+\".\"+VERSION.z.String + \" tests\"\nprint\n\nrunTestFolder: \"unit\", tru\n\nrunTestFolder: \"regression\", tru\n\nrunTestFolder: \"integration\", tru\n\nrunTestFolder: \"unfixed\", fls\n\nprint: \"tests done\"\n\nerrorDetails.len > 0 ?\n(\n\tprint\n\tprint: \"details\"\n\tprint\n\tprint: errorDetails\n)\n\nrunTestFolder :: {folder: String, printDetails: Bool}: (\n\t\n\tprint: (asciiEscape: 1) + in.folder + (asciiEscape: 0)\n\tprint: (asciiEscape: 2) + (asciiEscape: 3) + \"interpreted  transpiled   name                              \" + (asciiEscape: 0)\n\t\n\tfilepath: \"tests\" + pthslsh + in.folder\n\t\n\tcmd: String\n\t\n\tOS_IS_UNIX ? (\n\t\tcmd: \"ls \" + filepath + pthslsh + \" | grep .pn\"\n\t)|(\n\t\tcmd: \"dir /B \" + filepath + \" | FINDSTR /C:.pn\"\n\t)\n\t\n\tallFiles: runCmd: cmd\n\t\n\ti: 0\n\n\tj: 0 | j < allFiles.len | j: j+1 @ (\n\t\tj = allFiles.len-1 || (allFiles.sub: j, j+1) = \"\\n\" ?(\n\t\t\tname: allFiles.sub: i, j\n\t\t\trunTest: filepath + pthslsh + name, (name.sub: 0, name.len-3), in.printDetails\n\t\t\ti: j+1\n\t\t)\n\t)\n\t\n\tprint\n)\n\nrunTest :: {filepath: String, name: String, showDetails: Bool}:\n(\n\tcmdInput: \"./pinecone \" + in.filepath\n\t\n\tresultR: splitActualAndTarget: runCmd: cmdInput + \" -r\"\n\tresultE: splitActualAndTarget: runCmd: cmdInput + \" -e\"\n\t\n\tsummeryLine: String\n\t\n\tsummeryLine: summeryLine + \"    \"\n\tsummeryLine: summeryLine + (singleTest: resultR.actual, resultR.target, in.name + \" (interpreted)\", in.showDetails)\n\tsummeryLine: summeryLine + \"         \"\n\tsummeryLine: summeryLine + (singleTest: resultE.actual, resultE.target, in.name + \" (transpiled)\", in.showDetails)\n\tsummeryLine: summeryLine + \"       \"\n\tsummeryLine: summeryLine + in.name\n\t\n\tprint: summeryLine\n)\n\nsingleTest :: {actual: String, target: String, label: String, expectSuccess: Bool} -> {String}:\n(\n\tout: String\n\t\n\tin.actual = in.target ?\n\t(\n\t\tout: (asciiEscape: 1) + \" . \" + (asciiEscape: 0)\n\t)|(\n\t\tin.expectSuccess ?\n\t\t\tout: (asciiEscape: 91) + \"XXX\" + (asciiEscape: 0)\n\t\t|\n\t\t\tout: \"XXX\"\n\t\t\n\t\tin.expectSuccess ?\n\t\t(\n\t\t\terrorDetails: errorDetails + (getDiff: in.actual, in.target, in.label)\n\t\t)\n\t)\n\n\tout\n)\n\ngetDiff :: {actual: String, target: String, label: String} -> {String}:\n(\n\tactual: asciiEscape: 0\n\ttarget: asciiEscape: 0\n\t\n\tisMatching: tru\n\ti: 0 | i<in.actual.len || i<in.target.len | i: i+1 @\n\t(\n\t\tac: String\n\t\ttc: String\n\t\t\n\t\ti<in.actual.len ?\n\t\t\tac: in.actual.sub: i, i+1\n\t\t\n\t\ti<in.target.len ?\n\t\t\ttc: in.target.sub: i, i+1\n\t\t\n\t\tisNowMatching: ac=tc\n\t\t\n\t\t!(isNowMatching = isMatching) ?\n\t\t(\n\t\t\tisNowMatching ?\n\t\t\t(\n\t\t\t\tactual: actual + (asciiEscape: 0)\n\t\t\t\ttarget: target + (asciiEscape: 0)\n\t\t\t)|(\n\t\t\t\tactual: actual + (asciiEscape: 41) + (asciiEscape: 97)\n\t\t\t\ttarget: target + (asciiEscape: 42) + (asciiEscape: 97)\n\t\t\t)\n\t\t)\n\t\tisMatching: isNowMatching\n\t\t\n\t\t!isMatching ?\n\t\t(\n\t\t\t# add return symbol to make newlines visable\n\t\t\t\n\t\t\tac = \"\\n\" ?\n\t\t\t\tac: 226.ascii + 134.ascii + 181.ascii + ac\n\t\t\t\n\t\t\ttc = \"\\n\" ?\n\t\t\t\ttc: 226.ascii + 134.ascii + 181.ascii + tc\n\t\t)\n\t\t\n\t\tactual: actual + ac\n\t\ttarget: target + tc\n\t)\n\t\n\tout: String\n\t\n\tout: out + (asciiEscape: 1) + in.label + (asciiEscape: 0) + \"\\n\"\n\tout: out + (asciiEscape: 2) + \"actual:\" + (asciiEscape: 0) + \"\\n\"\n\tout: out + actual + (asciiEscape: 0)\n\tout: out + (asciiEscape: 2) + \"expected:\" + (asciiEscape: 0) + \"\\n\"\n\tout: out + target + (asciiEscape: 0)\n\tout: out + (asciiEscape: 2) + divideLine + (asciiEscape: 0) + \"\\n\\n\"\n\n\tout\n)\n\nasciiEscape :: {Int} -> {String}:\n(\n\t(27).ascii + \"[\" + in.String + \"m\"\n)\n\nsplitActualAndTarget :: {String} -> {actual: String, target: String}:\n(\n\tquit: fls\n\ti: 0\n\ttarget: String\n\tactual: String\n\t\n\t!quit @\n\t(\n\t\ti + targetActualSplit.len >= in.len ? (\n\t\t\ttarget: \"no target\\n\"\n\t\t\tin.len = 0 ?\n\t\t\t\tactual: \"no output\\n\"\n\t\t\t|\n\t\t\t\tactual: in\n\t\t\tquit: tru\n\t\t)\n\t\t| (in.sub: i, i+targetActualSplit.len) = targetActualSplit ?\n\t\t(\n\t\t\ttarget: in.sub: 0, i\n\t\t\tactual: in.sub: i+targetActualSplit.len, in.len\n\t\t\tquit: tru\n\t\t)|(\n\t\t\ti: i+1\n\t\t)\n\t)\n\n\tactual, target\n)\n\ntargetActualSplit :: \"_____\\n\"\ndivideLine :: (asciiEscape: 2) + \"==========================================================\\n\" + (asciiEscape: 0)\n"
  },
  {
    "path": "tests/unfixed/backslash_in_block_comment.pn",
    "content": "# test with backslash in a block comment\n\nprint: \"this should print\\nthis should also print\\n_____\"\n\nprint: \"this should print\"\n\n//\nprint: \"inside a comment, so this should not print\"\nprint: \"backslashes line \\\\ in string literal should not break block comment\"\n\\\\\n\nprint \"this should also print\"\n\n"
  },
  {
    "path": "tests/unit/conditionals.pn",
    "content": "# Pinecone conditionals test\nprint: \"3\\n5\\n_____\"\n\na: fls\nb: 10\n\na ?\n\tprint: 1\n|(\n\tb<3 ? (\n\t\tprint: 2\n\t)|(\n\t\tprint: 3\n\t\t\n\t\t6 = 9 ?\n\t\t\tprint: 4\n\t\t|\n\t\t\tprint: 5\n\t)\n)\n\n"
  },
  {
    "path": "tests/unit/constants.pn",
    "content": "# Pinecone constants test\nprint: \"21\\n_____\"\n\nprint: c*3\n\na :: 5\nc :: a+b\nb :: 2\n"
  },
  {
    "path": "tests/unit/destroyers_and_copiers.pn",
    "content": "# tests the calling of destroyers and copiers\n\nprint: \"copier called\\ncopier called\\n3\\ndestroyer called\\ndestroyer called\\n_____\"\n\nMyStruct :: {Int, Dub}\n\nMyStruct :: {} -> {MyStruct}: 3, 4.7\n\n__destroy__ :: {MyStruct}:\n(\n\tprint: \"destroyer called\"\n)\n\n__copy__ :: {MyStruct} -> {MyStruct}:\n(\n\tprint: \"copier called\"\n\tin\n)\n\n(\n\tmyStruct: MyStruct\n\ta: myStruct\n\tprint: a.a\n)\n"
  },
  {
    "path": "tests/unit/funcs.pn",
    "content": "# Pinecone funcs test\nprint: \"1\\n6\\n10\\n5\\n3\\n2\\n1\\n0\\n15\\n_____\"\n\nglobal: 14\n\nfunc0\nprint: func1: 8\nprint: func2: 1, 9\nprint: 2.func3: 3\nfunc4: 3\nfunc5\n\nfunc0 :: {}:\n(\n\tprint: 1\n)\n\nfunc1 :: {Int} -> {Int}:\n(\n\tin-2\n)\n\nfunc2 :: {v1: Int, v2: Int} -> {Int}:\n(\n\tin.v1+in.v2\n)\n\nfunc3 :: {Int}.{Int} -> {Int}:\n(\n\tme+in\n)\n\nfunc4 :: {Int}:\n(\n\tprint: in\n\tin > 0 ?\n\t\tfunc4: in-1\n)\n\nfunc5 :: {}:\n(\n\tglobal: global+1\n\tprint: global\n)\n\n"
  },
  {
    "path": "tests/unit/generate_windows_line_endings.sh",
    "content": "printf '# Pinecone Windows line endings test\\r\\nprint: \"good\\n_____\"\\r\\n\\r\\nprint: \"good\"' > windows_line_endings.pn\n\n"
  },
  {
    "path": "tests/unit/loops.pn",
    "content": "# Pinecone loops test\nprint: \"4\\n3\\n2\\n1\\n\\n0\\n1\\n2\\n3\\n4\\n5\\n_____\"\n\ni: 4\n\ni>0 @\n(\n\tprint: i\n\ti: i-1\n)\n\nprint\n\nj: 0 | j<6 | j: j+1 @\n(\n\tprint: j\n)\n"
  },
  {
    "path": "tests/unit/operators.pn",
    "content": "# Pinecone operators test\nprint: \"5\\n4.75\\n6\\n1\\n4\\n2\\n2.75\\n2\\nfls\\nfls\\ntru\\ntru\\ntru\\nfls\\ntru\\nfls\\n_____\"\n\nprint: 2+3\nprint: 1.5+3.25\nprint: 2*3\nprint: 3-2\nprint: 12/3\nprint: 11/4\nprint: 11.0/4.0\nprint: 17%5\nprint: 6=4\nprint: 9!=9\nprint: 6>4\nprint: 7<=7\nprint: tru && 4=4\nprint: tru && 4=2\nprint: tru || 4=2\nprint: !tru || 4=2\n\n"
  },
  {
    "path": "tests/unit/order_of_ops.pn",
    "content": "# Pinecone order of ops test\nprint: \"11\\n3\\n6\\ntru\\n_____\"\n\nprint: 4+2*3+1\nprint: 4-2+1\nprint: 1+8%5+2\nprint: 8>2=5.3<=7.9\n"
  },
  {
    "path": "tests/unit/strings.pn",
    "content": "# Pinecone strings test\nprint: \"hello\\na\\nbxyz\\nwe\\n6\\n4\\n89.342\\ntru\\nfls\\nfls\\n_____\"\n\nmyStr: \"hello\"\nprint: myStr\nprint: \"a\\nb\"+\"xyz\"\nprint: \"qwerty\".sub: 1, 3\nprint: \"qwerty\".len\nprint: 4.String\nprint: 89.342.String\nprint: \"abc\" = \"abc\"\nprint: \"abc\" = \"xyz\"\nprint: \"abc\" = \"abcd\"\n"
  },
  {
    "path": "tests/unit/type_info.pn",
    "content": "# tests various funcs that return info about types\n\nprint: \"String\\nInt\\n1\\n1\\n2\\n0\\n_____\"\n\nprint: \"hay\".typeName\n\nprint: Int.typeName\n\nprint: tru.typeSize\n\nprint: Byte.typeSize\n\nprint: (Bool, Byte).typeSize\n\nMyStruct ::\n{\n\tInt\n\tDub\n\tBool\n}\n\nMyStruct :: {} -> {MyStruct}: (Int, Dub, Bool)\n\nprint: MyStruct.typeSize - Int.typeSize - Dub.typeSize - Bool.typeSize\n\n"
  },
  {
    "path": "tests/unit/vars.pn",
    "content": "# Pinecone vars test\nprint: \"5.88\\n_____\"\n\na: 3\nb: 7.2\n\nprint: (Dub: a)+b/2.5\n"
  },
  {
    "path": "tests/unit/whatevs.pn",
    "content": "# tests use of the Whatev type\nprint: \"9\\n3.2\\nhay\\n4.7\\n4_\\nfls_\\n8.3\\n4.7\\nayy\\ntru\\n1.9\\ntru\\nyo\\n5\\ntru\\n9\\n7.1\\nwaddup\\n_____\"\n\nfunc0: 9\nfunc0: 3.2\nfunc0: \"hay\"\nfunc0: 4.7\n\n4.func1\nfls.func1\n\nfunc2: 8.3, 4.7\nfunc2: \"ayy\", tru\nfunc2: 1.9, tru\n\nfunc3: Struct0: \"yo\"\n\nprint: func4\n\nprint: func5: 7.1\nprint: func5: \"waddup\"\n\nfunc0 :: {Whatev}:\n(\n\tprint: in\n)\n\nfunc1 :: {Whatev}.{}:\n(\n\tprint: me.String + \"_\"\n)\n\nfunc2 :: {abc: Whatev, xyz: Whatev}:\n(\n\tprint: in.abc\n\tprint: in.xyz\n)\n\nStruct0 ::\n{\n\tfoo: Whatev\n\tbar: Int\n}\n\nStruct0 :: {Whatev} -> {Struct0}:\n(\n\tin, 5\n)\n\nfunc3 :: {Struct0}:\n(\n\tprint: in.foo\n\tprint: in.bar\n)\n\nfunc4 :: {} -> {Whatev}:\n(\n\tprint: tru\n\t9\n)\n\nfunc5 :: {Whatev} -> {Whatev}:\n(\n\tin\n)\n\n"
  },
  {
    "path": "tests/unit/windows_line_endings.pn",
    "content": "# Pinecone Windows line endings test\r\nprint: \"good\n_____\"\r\n\r\nprint: \"good\""
  },
  {
    "path": "tutorials/0_setting_up.md",
    "content": "# Setting up your environment\n\nDisclamer: these steps work on Linux, and usually on OSX. Windows is not yet supported. For updates on Windows support, see [this issue](https://github.com/william01110111/Pinecone/issues/2).\n\n1. Open a terminal and navigate to where you want the Pinecone folder to go\n2. Run the command `git clone https://github.com/william01110111/Pinecone.git`. This will download the Pinecone source code\n3. Move into the Pinecone directory\n4. run the command `make`. If you get a _command not found_ error, you may need to install make or g++.\n5. If all goes well, after a few seconds you should end up with a Pinecone executable in your current directory called `pinecone`.\n6. Run it with the command `./pinecone path/to/pinecone/source.pn`. If you don't have any Pinecone source code yet, test it with `./pinecone examples/hello_world.pn`\n7. If it works, you can now move on to the \"basic concepts\" tutorial\n\n[index](index.md) | [next: Basic Concepts ->](1_basic_concepts.md)\n\n"
  },
  {
    "path": "tutorials/1_basic_concepts.md",
    "content": "# Basic Concepts\n\nThe tutorials for most programming languages start with a hello world program, but Pinecone isn't most programming languages. Instead, lets start with a program that prints out something far more important.\n\n```\nprint: 42\n```\n\nThat's all you need in your file. No includes or boilerplate code of any sort. Just save that as a normal text file with the extension `.pn` and run it.\n\n## Primitive Types\n\n42 is an example of an __Int__, which is the same as an int in C++. It can hold positive and negative whole numbers. The other two primitive data types are Dub and Bool.\n\n__Dub__ is the same as a C++ double. It can hold decimal numbers. a Dub literal either ends with a d (ex: `47d`) or has a decimal point (ex: `47.0`). _NOTE: while a Dub literal can start with a decimal point, it can not end with one (ex: `.5` is valid but `5.` is not )_.\n\nA __Bool__ can only be `tru` or `fls`. If you think it should be `true` and `false` instead, you can email your complaints to williamwold@idontgiveafuck.com.\n\nA __String__ isn't really a primitive data type, but it is very common so I'll include it here anyway. It is a series of letters, numbers or other characters of any length. You make a string by surrounding text in double quotes.\n\n## Operators\n\nIn general, operators in Pinecone work the same as in any other language. It has all the ones you would expect with sensible order of operations. The following are the only major differences between operators in Pinecone and C-style langauges:\n* The assignment operator is `:` instead of `=`.\n* The equality operator is `=` instead of `==`.\n* There are no bitwise operators, they may be implemented at some point.\n* The short circuit aspect of boolean operators doesn't work yet, so `fls && functionReturningBool` will execute functionReturningBool. This will be fixed soon.\n\n## Calling Functions\n\n`print: 42` is an example of a function call. __print__ is a standard function that prints what it is sent, followed by an newline. the ':' indicates that you want to sent input to print and whatever follows is the input.\n\nFunctions can only take input of the exact type they are supposed to take (implicit casting will eventually be but is not yet implemented). Functions can, however be overloaded. This means there are multiple functions with the same name that are differentiated by what type their input is.\n\nprint is an overloaded function, so you can also do `print: 42.1`, or even just `print` and it will compile (the latter takes no input and so it will just print an empty line).\n\nFunctions can also take input from the left, but we will get to that later.\n\n## Variables\n\nA __variable__ is a place you can store a value. Every variable has a type, but types are deduced implicitly. To create, change and use a variable, simply do the following:\n\n```\nmyVarName: 88\nmyVarName: 12\nprint: myVarName\n```\n\n`myVarName` can be any series of letters, digits and underscores, as long as it doesn't start with a number. Variable names are case sensitive.\n\nAs you can see, creating a variable, setting a variable and calling a function with all look the same. This is a very important feature for the language, as it makes refactoring variables into calculations much easier.\n\n## Tuples\n\nA Tuple can be thought of as an ad hoc data structure. To construct one you simple combine several expressions with commas. The names of the elements of a tuple are `a`, `b`, `c`, etc. Elements can be accesed with the `.` operator. Here is an example:\n\n```\nmyTuple: 6, 2.9, fls\nprint: myTuple.c\nprint: myTuple.a\n```\n\nThe output of this will be\n\n```\n> fls\n> 6\n```\n\nTuple elements are supposed to be mutable, but this functionality is currently broken.\n\n## Constants\n\nA __constant__ is a value that is determined at compile time. Constants are created with the constants assignment operator `::`. You can declare constants above or below where you use them. Trying to set a constants more then once will result in a compile time error. Here is an example of a simple use of constants:\n\n```\na :: 3\nprint: b\nb :: a+c\nc :: 2\n```\n\nThis will compile correctly and print 5.\n\n## Comments\n\nComments are parts of your program that the compiler doesn't look at, so you can write notes and whatnot. In Pinecone, single-line comments start with a `#`. Multi-line comments start with `//` and end with `\\\\`.\n\n## Explicit Type Conversion\n\nSometimes, you might want to send a value to a variable or function of a different type. In the future, this will just work, but for now, you must convert it explicitly. To do this, call the target type's name like a function. For example:\n\n```\nmyDub: 12.7\nmyDub: 32       # won't work because 32 is an Int\nmyDub: Dub: 32  # explicit conversion\n```\n\n[index](index.md) | [next: Control Flow ->](2_control_flow.md)\n"
  },
  {
    "path": "tutorials/2_control_flow.md",
    "content": "# Control Flow\nIn Pinecone, control flow is done with symbols instead of keywords. There are two symbols used for control flow, `?` and `@`. `|` is used in conjunction with one of them.\n\n## If/Then\n\n`?` is used for ifs. You may be familiar with the ternary operator in C like languages. In Pinecone `?` can be used in much the same way (the only difference is `|` is used instead of `:`), but `?` is also used for all if statements with `|` being the 'else' operator. The body of an if statement is usually enclosed in parentheses, but this is optional if there is only one line in it. For 'else if', follow an else with another if statement. Here is an example:\n\n```\na: tru\nb: 8\n\na ?\n    print: 1\n\nb<4 ?\n    print: 2\n|\n    print: 3\n\na && b<7 ?\n(\n    print: 4\n)\n| b=8 ?\n(\n    print: 5\n)|(\n    print: 6\n)\n```\n\nThe output of that code is\n\n```\n> 1\n> 3\n> 5\n```\n\n## loops\n\n`@` is the loop operator. It is used for while and for loops.\n\nA simple while loop is below:\n\n```\ni: 8\n\ni>=0 @\n(\n    print: i\n    i: i-1\n)\n```\n\nLike if, the perenthesis would be optional if there was only one statement in the body.\n\nFor loops are are based on C for loops, in that the header consits of 3 expressions, the first sets it up, the second checks if to continue each iteration and the third increments a vairable. The expressions are seporated with `|`. Here is an example:\n\n```\ni: 0 | i<12 | i: i+1 @\n(\n    print: i\n)\n```\n\nThe output of this is the numbers 0-11.\n\n[index](index.md) | [next: Strings and Input ->](3_strings_and_input.md)\n\n"
  },
  {
    "path": "tutorials/3_strings_and_input.md",
    "content": "# Strings and Input\n\nIn Pinecone, like in many langauges, a string is a series of characters of any length. To make a string, simply suround some text in double quotes:\n\n```\nmyString: \"this is a string!!!\"\n```\n\n## Operators and Functions\n\nLike other types, there are various operators and functions that can be applied to strings.\n* `=` checks if two strings are exactly the same.\n* `+` combines two strings.\n* `stringName.len` returns the length of that string.\n* `68.ascii` will return a string one character long containing the ascii value of the int.\n* `stringName.sub: start, end` retuns a substring. I use start and end instead of start and length because start and length is stupid.\n* `84.String` will return a string with that number in base 10 (aka, normal). This can be done for Ints, Dubs and Bools.\n\n## String input\n\nYou can get a string as an input from the user. To do this, call `String.input`. This will block execution until they type sonething in and press enter, at which time the finction will return a string. If you want to give the user a prompt, call the function like this: `\"please enter some input: \".input`.\n\n[index](index.md) | [next: Structures and Functions ->](4_structures_and_functions.md)\n"
  },
  {
    "path": "tutorials/4_structures_and_functions.md",
    "content": "# Structures and Functions\n\n## Types\n\nSince types for variables are implicit, you usually don't have to specify them. The exception is when creating your own data structures and functions, when types are always enclosed in {}.\n\n## Data Structures\n\nStructures must be constants, so they are always delared with `::`. Your new type should be one or more other types inclosed in {}. Here is an example:\n\n```\nmyType :: {Int, Dub}\n```\n\nThe comma that seporates them is only for readability. It could be a semicolon, newline or just a space (NOTE: inside types is the only place a comma is interchangable with anything else). The elements in a data structure always have names. If none is specified, they are given the names `a`, `b`, `c`, etc. like tuples. You can specify your own names with `:`. For example:\n\n```\nmyType :: {\n\tname1: Int\n\tname2: Bool\n}\n```\n\n## Functions\n\nFunctions must currently be declared as constants. In the future, non constant functions (aka lambda expressions) will be possible. The types a function takes and returns must be explicity stated in the header. A function header looks like this `{leftInput}.{rightInput} -> {returnType}`. The header should be followed by a colon and a perenthesis enclosed list of statements.\n\n### Input and Output\nThe left input and return type can be omitted, in wich case they are `Void`. If you want the right input to be `Void`, simply leave the {} empty. Right input is the type of input you are already used to. Left input is a concept that is somewhat unique to Pinecone. It is just like right input, except that you call the function with `input.function` instead of `function: input`. A function can take both left and right input. The right input is named `in` and the left is named `me`. There is currently no return syntax in Pinecon, instead return value is the last expression in the function.\n\n### Examples\n\n```\n# declaring functions (can be done above or below calling them)\n\naddOne :: {Int} -> {Int}:\n(\n    a: in+1\n    a\n)\n\nprintNumbers :: {val1: Dub, val2: Dub}:\n(\n    print: in.val1\n    print: in.val2\n)\n\nleftInput :: {Int}.{} -> {String}:(\n\tprint: me\n\t\"return str\"\n)\n\nnoArgs :: {}: (\n\tprint: \"Hello\"\n)\n\n\n# calling functions\n\nprint: addOne: 8\n\nprintNumbers: 7, 12\n\nprint: 8.leftInput\n\nnoArgs\n```\n\nThe result of this code is\n\n```\n9\n7.0\n12.3\n8\nreturn str\nHello\n```\n\nI know the `in.` is annoying. It will be made implicit soon.\n\n## Overloading\nYou can make multiple functions with the same name as long as they take different types. This is called overloading. Overloading operators is not yet supported, but it will be.\n\n[index](index.md) | [next: Whatevs ->](5_whatevs.md)\n"
  },
  {
    "path": "tutorials/5_whatevs.md",
    "content": "# Whatevs\n\n## The Problem\nSometimes explicitly declaring a type is inconvenient. You don't want a function to always take an Int, String or any other specific type. You just want it to take whatev. Thats why Pinecone has the Whatev type.\n\n## How it Works\nWhatevs in Pinecone work very similar to templates and generics in other languages. You declare a function that takes a Whatev, and then the compiler makes different versions of that function for each type you try to send into it. Note that Whatevs do not enable dynamic typing at runtime. You can not make a Whatev variable except as an argument to a function.\n\n## Using Whatevs\nThe syntax is amazingly simple. Whatev is just a type, so you can use it like so:\n```\n# take any type, convert it to a string and return it wrapped in parenthesis\nputInPeren :: {Whatev} -> {Whatev}:\n(\n\t\"(\" + in.String + \")\"\n)\n\nprint: putInPeren: 8\nprint: putInPeren: tru\n```\nThe output of this code is\n```\n(8)\n(tru)\n```\nNote that all types you use this function with must have an overload of the .String function defined, else you'll get a compile time error.\n\n## Whatevs in Structs\nWhatevs can be used in structs. here is an example:\n```\n# define the struct\n\nMyWhatevStruct ::\n{\n\tfoo: Int\n\tbar: Whatev\n}\n\n# define the constructor\n\nmakeMyWhatevStruct :: {a: Int, b: Whatev} -> {MyWhatevStruct}:\n(\n\tin.a, in.b\n)\n\n# define the print function for makeMyWhatevStruct\n\nprint :: {MyWhatevStruct}:\n(\n\tprint: in.foo.String + \", \" + in.bar.String\n)\n\n# use the struct\n\na: makeMyWhatevStruct: 8, 9.3\nb: makeMyWhatevStruct: 2, fls\n\nprint: a\nprint: b\n```\nThe output of this is\n```\n8, 9.3\n2, fls\n```\n\n[index](index.md) | [next: Transpiling to C++ ->](6_transpiling_to_cpp.md)\n"
  },
  {
    "path": "tutorials/6_transpiling_to_cpp.md",
    "content": "# Transpiling to C++\n\nUp until now you have been running your Pinecone code the default way, which is currently with the interpreter. Pinecone can also transpile your code to C++. Here I will be explaining how to do that and what the pros and cons of transpiling are.\n\n## What is Interpreting, Compiling and Transpiling?\nTo compile is to turn one language into another. Generally this means turn a mid level human readable language (C, C++, Rust, etc.) into complex-for-us-but-easy-for-computers machene code that can be executed. When a language (such as Python, Ruby, JavaScript, etc.) is interpreted, the interpreter walks through the source code line by line and runs it as it goes. There are pros and cons of both compiling and interpreting. Generally, interpreting gives more flexibility while compiling gives more performence. Finally, transpiling is technically a subset of compileing. It is converting between two languages of roughly equal complexity. For example, you may want to transpile from a newer version of JS to an older one for compatibility reasons.\n\n## How This Relates to Pinecone\nPinecone has been designed from the begining with the restraints of a compiled langauge in mind. In the begining I implemented the language as interpreted, and the interpreter is still the default way to run Pinecone, but now you can also transpile to C++. This gives your peograms a huge speed boost. The interpreter is default because it doesn't need to write files to disk, it doesn't need an external compiler and there are some known rare cases where transpileing doesn't work.\n\n## Why Transpile to C++ Instead of Compiling Directly\nI tried to write a compiler with LLVM, but it was hard so I gave up.\n\n## Using the Transpiler\nThere are three command line arguments relevent transpiling `-cpp`, `-bin` and `-e`. These arguments can be used any combonation and if any are preasent, transpiling will be used instead of interpreting. `-cpp` and `-bin` should each be followed by a filepath which the transpiled source code and compiled binary executable will be saved to repectivly. `-e` should be used last, as subsequent arguments will be ignored. It means to actually execute the program, rather then just saving the output files. If cpp or bin file is not specified, they will be saved to a temporary file in your current directory which should be deleted automatically when the program is done. For compiling to a binary executable, and thus executing, the GCC compiler must be installed on your system.\n\n[index](index.md) | [next: Temporary Hacks ->](7_temporary_hacks.md)\n"
  },
  {
    "path": "tutorials/7_temporary_hacks.md",
    "content": "# Temporary Hacks\n\nPinecone is still under rapid development, and there are a lot of features that are not yet implemented. This tutorial explains what is coming and what you can use until then. many of the functions described here may be depricated/removed as soon as better replacements are ready.\n\n## Pass-by-reference\nThere is not yet any pass-by-reference in Pinecone (with the exception of Int arrays and strings (though the latter is immutable)). Without pass-by-reference, you can't really have classes because functions can not modify the object they are called on.\n\n## Arrays\nI have some very cool ideas for array syntax, but it is not ready yet. For now, you can have an array of ints with the built in class IntArray. Here is an example of how to use it:\n\n```\nmyArray: IntArray: 6                # 6 is the length of the array\n\ni: 0 | i<myArray.size | i: i+1 @\n(\n    myArray.set: i, i*2+1           # set index i to value i*2+1\n)\n\nprint: myArray.get: 2               # get the element at index 2\n\n```\n\nThe output is `5`.\n\n## Strings and Text\nAs of v0.3.0, strings work and the printc function is deprecated. It will be removed soon.\n\n## Input\nGetting string input works great (see string tutorial). Int input is not yet standardized, but you can call the function `inputInt` to get a number from the user.\n\n## imports\nImporting works similar to how it does in Python. It simply dumps another file into your current file. Right now, the import syntx is\n\n```\n==> \"path/to/target/file/from/current/file.pn\"\n```\n\nI may keep this syntax, but I'm not sure so I'm keeping it in this tutorial.\n\n## Linking with C++\nA highly suggested feature has been the ability to integrate Pinecone into C++ projects. There are a number of ways to do this with different trade offs, and hopefully there will be a complete solution at some point. In the mean time, there is a way to use 3rd party libraries with Pinecone via two functions, `cppCode` and `cppHead`. To use these you **must** transpile instead of interpret. `cppCode` lets you drop C++ source code directly into the transpiler output. `cppHead` is the same except it adds its code to the top of the source file (outside any function). It is useful for includes. Here is an example:\n\n```\ncppHead: \"#include <iostream>\"\ncppHead: \"using std::cout;\"\ncppHead: \"using std::endl;\"\n\na: 9\ncppCode: \"cout << a << endl;\"\ncppCode: \"a = 2;\"\nprint: a\n```\nWhen you transpile and run this, the output produced is\n```\n9\n2\n```\n\nYou can not get a return value from `cppCode`, nore can you declare a variable within it that is usable elsewhere. To get data out, you must create a variable of the correct type beforehand and set that variable within the C++ code. There is no way to call Pinecone functions from C++ code. Don't try to fine a workaround, it won't work. If you want to link with 3rd party libraries, you must transpile to a .cpp file and do the linking and compiling yourself.\n\n## Command Line Arguments\nUse `argLen` to get the number of arguments and `arg: argIndex` to get the string value of one. For example, here is a simple program to list all arguments:\n```\nprint: \"there are \" + argLen.String + \" args.\"\n\ni: 0 | i < argLen | i: i + 1 @ (\n\tprint: arg: i\n)\n```\nTo send args into a program, run the program with the `-r` or `-e` flag after the Pinecone source file name. All arguments after that will be sent in. The Pinecone source filepath will be the first arg. You can also compile the program and pass args in normally when running it without Pinecone.\n\n[index](index.md)\n"
  },
  {
    "path": "tutorials/index.md",
    "content": "# Pinecone Tutorial Index\n\n[About Pinecone](../readme.md)\n\n[0. Setting Up](0_setting_up.md)\n\n[1. Basic Concepts](1_basic_concepts.md)\n\n[2. Control Flow](2_control_flow.md)\n\n[3. Strings and Input](3_strings_and_input.md)\n\n[4. Structures and Functions](4_structures_and_functions.md)\n\n[5. Whatevs](5_whatevs.md)\n\n[6. Transpiling to C++](6_transpiling_to_cpp.md)\n\n[7. Temporary Hacks](7_temporary_hacks.md)\n\n\n"
  }
]