Showing preview only (351K chars total). Download the full file or copy to clipboard to get everything.
Repository: william01110111/Pinecone
Branch: master
Commit: a4550af6d58f
Files: 111
Total size: 324.4 KB
Directory structure:
gitextract_dt6obtpb/
├── .gitignore
├── LICENSE
├── Makefile
├── _config.yml
├── changelog.md
├── codeblocks/
│ ├── Pinecone.cbp
│ └── readme.md
├── examples/
│ ├── brainfuck.pn
│ ├── fizzBuzz.pn
│ ├── hello_world.pn
│ ├── historical/
│ │ └── snake_original.pn
│ ├── incomplete/
│ │ └── hashmap.pn
│ ├── morse.pn
│ ├── queue.pn
│ ├── readme.md
│ ├── simple_demo.pn
│ └── snake_new.pn
├── h/
│ ├── Action.h
│ ├── AllOperators.h
│ ├── AstNode.h
│ ├── CppProgram.h
│ ├── ErrorHandler.h
│ ├── Namespace.h
│ ├── Operator.h
│ ├── PineconeProgram.h
│ ├── SourceFile.h
│ ├── StackFrame.h
│ ├── Token.h
│ ├── Type.h
│ ├── VERSION.h
│ ├── msclStringFuncs.h
│ └── utils/
│ ├── fileUtils.h
│ ├── stringArray.h
│ ├── stringDrawing.h
│ ├── stringNumConversion.h
│ └── stringUtils.h
├── other/
│ ├── pinecone.pn
│ ├── pinecone_concept.txt
│ ├── readme.md
│ └── user_testing.txt
├── readme.md
├── repl/
│ ├── readme.md
│ └── repl.sh
├── src/
│ ├── Actions/
│ │ ├── Action.cpp
│ │ ├── BoolOpAction.cpp
│ │ ├── BranchAction.cpp
│ │ ├── FunctionAction.cpp
│ │ ├── IfAction.cpp
│ │ ├── ListAction.cpp
│ │ ├── LoopAction.cpp
│ │ ├── MakeTupleAction.cpp
│ │ ├── TypeAction.cpp
│ │ └── VarAction.cpp
│ ├── AllOperators.cpp
│ ├── AstNode.cpp
│ ├── CppProgram.cpp
│ ├── ErrorHandler.cpp
│ ├── Lexer.cpp
│ ├── Namespace.cpp
│ ├── Parser.cpp
│ ├── PineconeProgram.cpp
│ ├── PineconeStdLib.cpp
│ ├── ResolveLiteral.cpp
│ ├── SourceFile.cpp
│ ├── StackFrame.cpp
│ ├── Token.cpp
│ ├── Type.cpp
│ ├── main.cpp
│ ├── msclStringFuncs.cpp
│ └── utils/
│ ├── fileUtils.cpp
│ ├── stringArray.cpp
│ ├── stringDrawing.cpp
│ ├── stringNumConversion.cpp
│ └── stringUtils.cpp
├── tests/
│ ├── integration/
│ │ ├── brainfuck.pn
│ │ ├── morse.pn
│ │ └── queue.pn
│ ├── readme.md
│ ├── regression/
│ │ ├── bool_short_circuit.pn
│ │ ├── cpp_bad_escape_seq.pn
│ │ ├── cpp_global_and_local_same_name.pn
│ │ ├── error_on_nonexistant_file.pn
│ │ ├── function_with_one_named_arg.pn
│ │ ├── if_as_ternary.pn
│ │ ├── multiple_left_inputs.pn
│ │ ├── negative_literal.pn
│ │ └── no_newline_at_end.pn
│ ├── run_tests.pn
│ ├── unfixed/
│ │ └── backslash_in_block_comment.pn
│ └── unit/
│ ├── conditionals.pn
│ ├── constants.pn
│ ├── destroyers_and_copiers.pn
│ ├── funcs.pn
│ ├── generate_windows_line_endings.sh
│ ├── loops.pn
│ ├── operators.pn
│ ├── order_of_ops.pn
│ ├── strings.pn
│ ├── type_info.pn
│ ├── vars.pn
│ ├── whatevs.pn
│ └── windows_line_endings.pn
└── tutorials/
├── 0_setting_up.md
├── 1_basic_concepts.md
├── 2_control_flow.md
├── 3_strings_and_input.md
├── 4_structures_and_functions.md
├── 5_whatevs.md
├── 6_transpiling_to_cpp.md
├── 7_temporary_hacks.md
└── index.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# object files
*.o
# codeblocks project files
*.layout
*.depend
*.cscope_file_list
# Valgrind
*cachegrind.out*
*ValgrindOut.xml
# executables
PineconeDbg
PineconeBin
Pinecone
pinecone
#KDevelop
.kdev4
# stupid OSX stuff
*.DS_Store
# repl temp file
repl/tmp.pn
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2017 Sophie Winter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: Makefile
================================================
# I'm totally aware how shitty this makefile is
# I use the IDE Code::Blocks; this is only for people who don't have that
# I'll write a proper makefile at some point
build:
g++ -Wall -std=c++11 -O2 src/*.cpp src/Actions/*.cpp src/utils/*.cpp -o pinecone
================================================
FILE: _config.yml
================================================
theme: jekyll-theme-hacker
================================================
FILE: changelog.md
================================================
# Pinecone Changelog
This file documents all major changes to the Pinecone langauge.
Every new version gets a number of minor bug fixes, so they are not included
### v0.5.1 (April 20, 2017)
* Fixed silent error when file fails to load
* Fixed known bug with functions that take one named argument
* Fixed known bug that prevented `?` being useed in a ternary expression
* Improved output of testing script
* Internal codebase cleanup
## v0.5.0 (April 14, 2017)
* Made `&&` and `||` use short circuiting
* Improved testing system
* Added support for Windows
* __Added Whatev type__ for compile time dynamic typing and implicit function return type
## v0.4.0 (Mar 26, 2017)
* Added command line options for transpileing
* __Fully implemented transpiler to C++__
* Disabled implicit conversion between two structs (if neither is an anonymous tuple)
* Added `!=` operator
* Wrote more example programs including a brainfuck interpreter
* Fixed bug that prevented accessing multiple layers of structures with dot ('struct.data.func: arg' now works)
* Added a wide range of unit tests and integration tests
* Added escape character support to Strings
* Added support for running shell commands
* Added explicit conversion of primitive types to Strings
* Improved tutorial navigation
## v0.3.0 (Jan 18, 2017)
* __Added string literal support__
* Added various functions and operators for strings
* Fixed globals
### v0.2.1 (Jan 16, 2017)
* Fixed bug introduced in v0.2.0 with functions
* Fixed bug with line numbers in error messages
## v0.2.0 (Jan 16, 2017)
* Added file import feature
* Flipped open and close block comments
* Removed debugging info by default
* Added command line args
## v0.1.0 (Jan 15, 2017)
* __Created Pinecone__
## v0.0.0
* Pinecone did not exist
================================================
FILE: codeblocks/Pinecone.cbp
================================================
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="Pinecone" />
<Option pch_mode="2" />
<Option default_target="Release" />
<Option compiler="gcc" />
<Build>
<Target title="Debug_R">
<Option output="../pinecone" prefix_auto="1" extension_auto="1" />
<Option working_dir="../" />
<Option type="1" />
<Option compiler="gcc" />
<Option parameters="other/pinecone.pn -d -r" />
<Compiler>
<Add option="-g" />
</Compiler>
</Target>
<Target title="Debug_E">
<Option output="../pinecone" prefix_auto="1" extension_auto="1" />
<Option working_dir="../" />
<Option type="1" />
<Option compiler="gcc" />
<Option parameters="other/pinecone.pn -d -e" />
<Compiler>
<Add option="-g" />
</Compiler>
</Target>
<Target title="Test">
<Option output="../pinecone" prefix_auto="1" extension_auto="1" />
<Option working_dir="../" />
<Option type="1" />
<Option compiler="gcc" />
<Option parameters="tests/run_tests.pn" />
<Compiler>
<Add option="-g" />
</Compiler>
</Target>
<Target title="Release">
<Option output="../pinecone" prefix_auto="1" extension_auto="1" />
<Option working_dir="../" />
<Option type="1" />
<Option compiler="gcc" />
<Option parameters="-v" />
<Compiler>
<Add option="-O2" />
</Compiler>
<Linker>
<Add option="-s" />
</Linker>
</Target>
</Build>
<Compiler>
<Add option="-O" />
<Add option="-Wall" />
<Add option="-std=c++11" />
<Add option="-fexceptions" />
</Compiler>
<Unit filename="../h/Action.h" />
<Unit filename="../h/AllOperators.h" />
<Unit filename="../h/AstNode.h" />
<Unit filename="../h/CppProgram.h" />
<Unit filename="../h/ErrorHandler.h" />
<Unit filename="../h/Namespace.h" />
<Unit filename="../h/Operator.h" />
<Unit filename="../h/PineconeProgram.h" />
<Unit filename="../h/SourceFile.h" />
<Unit filename="../h/StackFrame.h" />
<Unit filename="../h/Token.h" />
<Unit filename="../h/Type.h" />
<Unit filename="../h/VERSION.h" />
<Unit filename="../h/msclStringFuncs.h" />
<Unit filename="../h/utils/fileUtils.h" />
<Unit filename="../h/utils/stringArray.h" />
<Unit filename="../h/utils/stringDrawing.h" />
<Unit filename="../h/utils/stringNumConversion.h" />
<Unit filename="../h/utils/stringUtils.h" />
<Unit filename="../other/pinecone.pn" />
<Unit filename="../other/pinecone_concept.txt" />
<Unit filename="../readme.md" />
<Unit filename="../src/Actions/Action.cpp" />
<Unit filename="../src/Actions/BoolOpAction.cpp" />
<Unit filename="../src/Actions/BranchAction.cpp" />
<Unit filename="../src/Actions/FunctionAction.cpp" />
<Unit filename="../src/Actions/IfAction.cpp" />
<Unit filename="../src/Actions/ListAction.cpp" />
<Unit filename="../src/Actions/LoopAction.cpp" />
<Unit filename="../src/Actions/MakeTupleAction.cpp" />
<Unit filename="../src/Actions/TypeAction.cpp" />
<Unit filename="../src/Actions/VarAction.cpp" />
<Unit filename="../src/AllOperators.cpp" />
<Unit filename="../src/AstNode.cpp" />
<Unit filename="../src/CppProgram.cpp" />
<Unit filename="../src/ErrorHandler.cpp" />
<Unit filename="../src/Lexer.cpp" />
<Unit filename="../src/Namespace.cpp" />
<Unit filename="../src/Parser.cpp" />
<Unit filename="../src/PineconeProgram.cpp" />
<Unit filename="../src/PineconeStdLib.cpp" />
<Unit filename="../src/ResolveLiteral.cpp" />
<Unit filename="../src/SourceFile.cpp" />
<Unit filename="../src/StackFrame.cpp" />
<Unit filename="../src/Token.cpp" />
<Unit filename="../src/Type.cpp" />
<Unit filename="../src/main.cpp" />
<Unit filename="../src/msclStringFuncs.cpp" />
<Unit filename="../src/utils/fileUtils.cpp" />
<Unit filename="../src/utils/stringArray.cpp" />
<Unit filename="../src/utils/stringDrawing.cpp" />
<Unit filename="../src/utils/stringNumConversion.cpp" />
<Unit filename="../src/utils/stringUtils.cpp" />
<Unit filename="../tests/run_tests.pn" />
<Unit filename="../tutorials/0_setting_up.md" />
<Unit filename="../tutorials/1_basic_concepts.md" />
<Unit filename="../tutorials/2_control_flow.md" />
<Unit filename="../tutorials/3_strings_and_input.md" />
<Unit filename="../tutorials/4_structures_and_functions.md" />
<Unit filename="../tutorials/5_transpiling_to_cpp.md" />
<Unit filename="../tutorials/6_temporary_hacks.md" />
<Unit filename="../tutorials/index.md" />
<Extensions>
<code_completion />
<envvars />
<debugger />
<lib_finder disable_auto="1" />
</Extensions>
</Project>
</CodeBlocks_project_file>
================================================
FILE: codeblocks/readme.md
================================================
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.
================================================
FILE: examples/brainfuck.pn
================================================
//
This is an interpreter for the esoteric programming language brainfuck
\\
data: IntArray: 40000
offset: 0
error: fls
inText: ""
j: 0 | j<data.len | j: j+1 @
data.set: j, 0
code: "enter your brainfuck code: ".input
#code: "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>."
processSection: code, 0, tru
error ?
(
print: "program aborted due to error"
print: "position at exit:"
print: offset
)
# runs a loop of bf code, returns when done
processSection :: {src: String, start: Int, isTopLevel: Bool}: (
i: (in.start)
quit: fls
!quit && !error @ (
c: in.src.sub: i, i+1
c = "<" ? (
offset: offset-1
offset < 0 ? (
print: "you went too far left"
error: tru
)
)
| c = ">" ? (
offset: offset+1
offset >= data.len ? (
print: "you went too far right"
error: tru
)
)
| c = "+" ? (
data.set: offset, (data.get: offset)+1
)
| c = "-" ? (
data.set: offset, (data.get: offset)-1
)
| c = "." ? (
printc: data.get: offset
)
| c = "," ? (
data.set: offset, inputc
)
| c = "[" ? (
processSection: in.src, i+1, fls
i: skipBrace: in.src, i
)
| c = "]" ? (
in.isTopLevel ? (
print: "']' without matching '['"
error: tru
)|(
(Bool: data.get: offset) ? (
i: in.start-1
)|(
quit: tru
)
)
)
i: i+1
i >= in.src.len ? (
in.isTopLevel ? (
quit: tru
)|(
print: "'[' without matching ']'"
error: tru
)
)
)
)
skipBrace :: {src: String, i: Int} -> {Int}: (
i: in.i
(in.src.sub: i, i+1) != "[" ? (
print: "skipBrace called on character other then '['"
error: tru
)|(
i: i+1
!error && (in.src.sub: i, i+1) != "]" @ (
i: i+1
i >= in.src.len ? (
print: "'[' without matching ']'"
error: tru
)
)
)
i
)
#>++++++++[-<+++++++++>]<.>>+>-[+]++>++>+++[>[->+++<<+++>]<<]>-----.>->+++..+++.>-.<<+[>[+>+]>>]<--------------.>>.+++.------.--------.>+.>+.
================================================
FILE: examples/fizzBuzz.pn
================================================
# FizzBuzz
# call the function defined below
fizzBuzz: 1, 20
# define the FizzBuzz function
fizzBuzz :: {start: Int, end: Int}: (
# loop i from start to end
i: in.start | i <= in.end | i: i+1 @ (
# use conditionals to print the right thing
i % 3 = 0 && i % 5 = 0 ?
print: "FizzBuzz"
|
i % 3 = 0 ?
print: "Fizz"
|
i % 5 = 0 ?
print: "Buzz"
|
print: i
)
)
================================================
FILE: examples/hello_world.pn
================================================
print: "Hello World!"
================================================
FILE: examples/historical/snake_original.pn
================================================
# this was written on Jan 12th, 2016.
# this is the first complex pinecone program ever wretten.
# type the numbers 1, 2, 3 and 4 followed by enter to move.
# because of how early it was wretten, it doesn't use modern constructs, like functions.
w :: 16
h :: 8
meChar :: 79
trailChar :: 43
# init
locX: w/2
locY: h/2
quit: fls
ary: IntArray: w*h
y: 0 | y<h | y: y+1 @
(
x: 0 | x<w | x: x+1 @
(
ary.set: y*w+x, 32
)
)
# game loop
!quit @
(
# update
locX<0? locX: 0
locX>=w? locX: w-1
locY<0? locY: 0
locY>=h? locY: h-1
(ary.get: locY*w+locX)=trailChar ?
(
quit: tru
)|(
ary.set: locY*w+locX, trailChar
# display board
i: 0 | i<6 | i: i+1 @
print
printc: 32
x: 0 | x<w | x: x+1 @
printc: 45
print
y: 0 |y<h |y: y+1 @
(
printc: 124
x: 0 | x<w | x: x+1 @
(
x=locX && y=locY ?
printc: meChar
|
printc: ary.get: y*w+x
)
printc: 124
print
)
printc: 32
x: 0 | x<w | x: x+1 @
printc: 45
3
print
# get input
valid: fls
!valid @
(
dir: inputInt
valid: tru
dir=3 ?
locY: locY+1
| dir=4 ?
locX: locX+1
| dir=2 ?
locY: locY-1
| dir=1 ?
locX: locX-1
|
valid: fls
)
)
)
print
printc: 88
printc: 32
printc: 88
print
printc: 45
printc: 45
printc: 45
print
================================================
FILE: examples/incomplete/hashmap.pn
================================================
Hashmap :: {used: IntArray, keys: IntArray, vals: IntArray}
Hashmap :: {} -> {Hashmap}:
(
size: 10
used: (IntArray: size)
i: 0 | i<used.len | i: i+1 @ (
used.set: i, 0
)
used, (IntArray: size), (IntArray: size)
)
Hashmap :: {size: Int} -> {Hashmap}:
(
used: (IntArray: size)
i: 0 | i<used.len | i: i+1 @ (
used.set: i, 0
)
used, (IntArray: size), (IntArray: size)
)
insert :: {Hashmap}.{key: Int, val: Int}:
(
i: in.key % me.used.len
start: i
Bool: me.used.get: i @ (
i: (i+1) % me.used.len
#i = start ?
# me.expand
)
me.used.set: i, 1
me.keys.set: i, in.key
me.vals.set: i, in.val
)
len :: {Hashmap}.{} -> {Int}: me.keys.len
String :: {Hashmap} -> {String}:
(
out: "hashmap:\n"
i: 0 | i<in.len | i: i+1 @
(
Bool: in.used.get: i ?
out: out + "\t" + (in.keys.get: i).String + ": " + (in.vals.get: i).String + "\n"
)
out
)
a: Hashmap
a.insert: 4, 82
a.insert: 14, 89
print: String: a
================================================
FILE: examples/morse.pn
================================================
# this program converts text into morse code
# this constant string will act as the data source for the conversion
key :: "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----- ..-.-.- ?..--.. "
# loop until the user types "quit"
quit: fls
!quit @
(
# get input
inStr: "enter some text or type quit: ".input
inStr = "quit" ?
quit: tru
|
print: stringToMorse: inStr
)
print
stringToMorse :: {String} -> {String}:
(
out: ""
i: 0 | i<in.len | i: i+1 @
(
letter: in.sub: i, i+1
letter = " " ?
out: out+" "
|
out: out+(letterToMorse: letter)+" "
)
out
)
letterToMorse :: {String} -> {String}:
(
out: ""
found: fls
i: 0 | i<key.len && !found | i: i+1 @
(
(key.sub: i, i+1) = in ?
(
j: i+1
!((key.sub: j, j+1) = " ") @
j: j+1
out: key.sub: i+1, j
found: tru
)
)
!found ?
out: "[" + in + "]"
out
)
================================================
FILE: examples/queue.pn
================================================
# this is an implementation of a queue using a dynamically sized circular buffer
# 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
q: Queue
main
main :: {}:
(
enqueue: 1
enqueue: 2
enqueue: 3
enqueue: 4
enqueue: 5
enqueue: 6
print: dequeue
print: dequeue
print: dequeue
print: dequeue
enqueue: 7
enqueue: 8
enqueue: 9
print: dequeue
print: dequeue
print: q
)
Queue :: {array: IntArray, offset: Int, len: Int}
Queue :: {} -> {Queue}: (
(IntArray: 1), 0, 0
)
resize :: {Int}: (
newArray: IntArray: in
i: 0 | i<q.len | i: i+1 @ (
tmp: q.array
newArray.set: i, (tmp.get: (i+q.offset)%q.array.len)
)
q: newArray, 0, q.len
)
enqueue :: {Int}: (
q.len >= q.array.len ?
resize: q.array.len*2
q: q.array, q.offset, q.len+1
tmp: q.array
tmp.set: (q.offset+q.len-1)%q.array.len, in
)
dequeue :: {} -> {Int}: (
tmp: q.array
out: tmp.get: q.offset%q.array.len
q: q.array, q.offset+1, q.len-1
q.len < q.array.len/3+1 ?
resize: q.array.len/3+1
out
)
peek :: {}: (
tmp: q.array
tmp.get: q.offset%q.array.len
)
print :: {Queue}: (
print: "queue {"
i: 0 | i<in.len | i: i+1 @ (
#Bool: i ?
# print: ", "
ary: in.array
print: " "+(ary.get: (i+in.offset)%in.array.len).String
)
print: "}"
print
//
print: "raw array {"
i: 0 | i<in.array.len | i: i+1 @ (
#Bool: i ?
# print: ", "
ary: in.array
out: (ary.get: i).String
i = in.offset ?
out: " -> "+out
| i = (in.offset+in.len-1)%in.array.len ?
out: " -| "+out
|
out: " "+out
print: out
)
print: "}"
print
\\
)
================================================
FILE: examples/readme.md
================================================
These are some examples of working Pinecone source code
================================================
FILE: examples/simple_demo.pn
================================================
//
This file demonstrates the basic syntax constructs of Pinecone
to run, simply run command
path/to/pinecone/executable simple_demo.pn
\\
# that was a multi line comment. this is a single line comment
# create a variable
a: 12 # deduces the type as Int
# print the value in the variable
print: a
print # print an empty line
print: "if/then"
b: 7
a = 9 ?
(
print: 1
)|(
print: 2
)
b>3 ?
(
print: 3
)
print
print: "while loop"
i: 12
i>3 @
(
print: i
i: i-1
)
print
print: "for loop"
i: 0 | i<10 | i: i+1 @
(
print: i
)
print
print: "functions"
print: func: 7
func :: {Int} -> {Dub}:
(
(Dub: in)/2.0
)
print
print: "Fibonacci"
b: 0
a: 1
a<100 @
(
print: a
tmp: a
a: a+b
b: tmp
)
print
print: "Recursive Fibonacci"
fib :: {Int} -> {Int}: (
out: Int
in <= 1 ?
out: 1
|
out: (fib: in - 1) + (fib: in - 2)
out
)
print: fib: 8
print
print: "compile time constants"
# these can be declared in any order
print: y
x :: 10
y :: x+z
z :: 4
================================================
FILE: examples/snake_new.pn
================================================
# this is an updated version of the original Pinecone snake game
# use WASD to move
w :: 16
h :: 8
meChar :: 79
trailChar :: 43
# init
locX: w/2
locY: h/2
quit: fls
ary: IntArray: w*h
clearBoard
# game loop
!quit @
(
# update
locX<0? locX: 0
locX>=w? locX: w-1
locY<0? locY: 0
locY>=h? locY: h-1
(ary.get: locY*w+locX)=trailChar ?
(
quit: tru
)|(
drawBoard
ary.set: locY*w+locX, trailChar
# get input
valid: fls
!valid @
(
dir: "use WASD to move, then press return: ".input
valid: tru
dir="s" ?
locY: locY+1
| dir="d" ?
locX: locX+1
| dir="w" ?
locY: locY-1
| dir="a" ?
locX: locX-1
|
valid: fls
)
)
)
clearBoard :: {}:
(
y: 0 | y<h | y: y+1 @
(
x: 0 | x<w | x: x+1 @
(
ary.set: y*w+x, 32
)
)
)
drawBoard :: {}:
(
i: 0 | i<12 | i: i+1 @
print
line: " "
x: 0 | x<w | x: x+1 @
line: line+"-"
print: line
line: ""
y: 0 |y<h |y: y+1 @
(
line: line+"|"
x: 0 | x<w | x: x+1 @
(
x=locX && y=locY ?
line: line+(meChar.ascii)
|
line: line+(ary.get: y*w+x).ascii
)
line: line+"|"
print: line
line: ""
)
line: " "
x: 0 | x<w | x: x+1 @
line: line+"-"
print: line
)
print
printc: 88
printc: 32
printc: 88
print
printc: 45
printc: 45
printc: 45
print
================================================
FILE: h/Action.h
================================================
#pragma once
#include "StackFrame.h"
#include "Type.h"
#include "CppProgram.h"
#include <functional>
#include <memory>
#include <vector>
#include <string>
#include "utils/stringDrawing.h"
#include <stdlib.h> // malloc() and free() on some systems
using std::shared_ptr;
using std::unique_ptr;
using std::to_string;
using std::function;
using std::vector;
class ActionData;
extern shared_ptr<ActionData> voidAction;
class ActionData
{
public:
ActionData(Type returnTypeIn, Type inLeftTypeIn, Type inRightTypeIn);
virtual ~ActionData() {}
void setDescription(string in) {description=in;}
//void setText(string in) {text=in;}
//string getText() {return text;}
string toString();
string getTypesString();
virtual bool isFunction() {return false;}
Type& getReturnType() {return returnType;}
Type& getInLeftType() {return inLeftType;}
Type& getInRightType() {return inRightType;}
//void* execute(void* inLeft, void* inRight);
virtual string getDescription() {return description;}
virtual void* execute(void* inLeft, void* inRight)=0;
//virtual string getCSource(string inLeft="", string inRight="")=0;
virtual void addToProg(shared_ptr<ActionData> inLeft, shared_ptr<ActionData> inRight, CppProgram* prog)
{
prog->comment("action '"+getDescription()+"' to cpp code not yet implemented");
}
void addToProg(CppProgram* prog) {addToProg(voidAction, voidAction, prog);}
// void addToProg(Action inLeft, Action inRight, CppProgram* prog)
string nameHint="";
protected:
//string text;
Type returnType;
Type inLeftType;
Type inRightType;
string description;
//virtual DataElem * privateExecute(DataElem * inLeft, DataElem * inRight)=0;
};
typedef shared_ptr<ActionData> Action;
class AstNodeBase;
//Action lambdaAction(Type returnTypeIn, function<void*(void*,void*)> lambdaIn, Type inLeftTypeIn, Type inRightTypeIn, string textIn);
Action lambdaAction(Type inLeftTypeIn, Type inRightTypeIn, Type returnTypeIn, function<void*(void*,void*)> lambdaIn, function<void(Action inLeft, Action inRight, CppProgram* prog)> addCppToProg, string textIn);
Action createNewVoidAction();
Action branchAction(Action leftInputIn, Action actionIn, Action rightInputIn);
Action functionAction(Action actionIn, shared_ptr<StackFrame> stackFameIn);
Action functionAction(unique_ptr<AstNodeBase> nodeIn, Type returnTypeIn, shared_ptr<StackFrame> stackFameIn);
Action andAction(Action firstActionIn, Action secondActionIn);
Action orAction(Action firstActionIn, Action secondActionIn);
Action ifAction(Action conditionIn, Action ifActionIn);
Action ifElseAction(Action conditionIn, Action ifActionIn, Action elseAction);
Action listAction(const std::vector<Action>& actionsIn, const std::vector<Action>& destroyersIn);
Action loopAction(Action conditionIn, Action loopActionIn);
Action loopAction(Action conditionIn, Action endActionIn, Action loopActionIn);
Action makeTupleAction(const std::vector<Action>& sourceActionsIn);
//Action getElemFromTupleAction(Action source, string name);
Action getElemFromTupleAction(Type source, string name);
Action cppTupleCastAction(Action actionIn, Type returnType);
Action varGetAction(size_t in, Type typeIn, string idIn);
Action varSetAction(size_t in, Type typeIn, string idIn);
Action globalGetAction(size_t in, Type typeIn, string idIn);
Action globalSetAction(size_t in, Type typeIn, string idIn);
class NamespaceData;
Action constGetAction(const void* in, Type typeIn, string idIn, shared_ptr<NamespaceData> ns);
Action typeGetAction(Type typeIn);
================================================
FILE: h/AllOperators.h
================================================
#pragma once
#include <vector>
using std::vector;
#include <unordered_map>
using std::unordered_map;
#include "Operator.h"
class AllOperators
{
public:
// sets ops to a new instance
static void init();
// sets out to the operators (0, 1 or more) for the given text
void get(string text, vector<Operator>& out);
/*
#define DECLARE_OP(name, text, left, right, overload)\
const Operator name{new OperatorData(text, left, right, overload)};
#define ALL_OPS \
DECLARE_OP( loop, "@", 5, 5, false ); \
DECLARE_OP( ifOp, "?", 5, 5, false ); \
DECLARE_OP( pipe, "|", 10, 10, false ); \
DECLARE_OP( plus, "+", 20, 21, true ); \
DECLARE_OP( minus, "-", 20, 21, true ); \
DECLARE_OP( multiply, "*", 30, 31, true ); \
DECLARE_OP( divide, "/", 30, 31, true ); \
DECLARE_OP( equal, "=", 40, 41, true ); \
DECLARE_OP( greater, ">", 40, 41, true ); \
DECLARE_OP( less, "<", 40, 41, true ); \
DECLARE_OP( comma, ",", 60, 61, false ); \
DECLARE_OP( dot, ".", 70, 71, false ); \
DECLARE_OP( doubleColon,"::", 13, 12, false ); \
DECLARE_OP( colon, ":", 15, 14, false ); \
DECLARE_OP( openPeren, "(", 0, 100, false ); \
DECLARE_OP( closePeren, ")", 100, 0, false ); \
DECLARE_OP( openSqBrac, "[", 0, 100, false ); \
DECLARE_OP( closeSqBrac,"]", 100, 0, false ); \
DECLARE_OP( openCrBrac, "{", 0, 100, false ); \
DECLARE_OP( closeCrBrac,"}", 100, 0, false ); \
*/
#define DECLARE_OP(name, text, prece, input, overload)\
const Operator name{new OperatorData(text, prece, input, overload)};
#define ALL_OPS \
DECLARE_OP( loop, "@", 5, OperatorData::BOTH, false ); \
DECLARE_OP( ifOp, "?", 6, OperatorData::BOTH, false ); \
DECLARE_OP( pipe, "|", 6, OperatorData::BOTH, false ); \
DECLARE_OP( colon, ":", 24, OperatorData::BOTH, false ); \
DECLARE_OP( doubleColon,"::", 24, OperatorData::BOTH, false ); \
DECLARE_OP( comma, ",", 35, OperatorData::BOTH, false ); \
DECLARE_OP( orOp, "||", 36, OperatorData::BOTH, false ); \
DECLARE_OP( andOp, "&&", 38, OperatorData::BOTH, false ); \
DECLARE_OP( equal, "=", 40, OperatorData::BOTH, true ); \
DECLARE_OP( notEqual, "!=", 40, OperatorData::BOTH, false ); \
DECLARE_OP( greater, ">", 50, OperatorData::BOTH, true ); \
DECLARE_OP( less, "<", 50, OperatorData::BOTH, true ); \
DECLARE_OP( greaterEq, ">=", 50, OperatorData::BOTH, true ); \
DECLARE_OP( lessEq, "<=", 50, OperatorData::BOTH, true ); \
DECLARE_OP( plus, "+", 61, OperatorData::BOTH, true ); \
DECLARE_OP( minus, "-", 61, OperatorData::BOTH, true ); \
DECLARE_OP( multiply, "*", 71, OperatorData::BOTH, true ); \
DECLARE_OP( divide, "/", 71, OperatorData::BOTH, true ); \
DECLARE_OP( mod, "%", 70, OperatorData::BOTH, true ); \
DECLARE_OP( notOp, "!", 74, OperatorData::RIGHT, true ); \
DECLARE_OP( plusPlus, "++", 75, OperatorData::LEFT, false ); \
DECLARE_OP( minusMinus, "--", 75, OperatorData::LEFT, false ); \
DECLARE_OP( dot, ".", 81, OperatorData::BOTH, false ); \
DECLARE_OP( rightArrow, "->", 83, OperatorData::BOTH, false ); \
DECLARE_OP( import, "==>", 90, OperatorData::RIGHT, false ); \
DECLARE_OP( openPeren, "(", 100, OperatorData::RIGHT, false ); \
DECLARE_OP( closePeren, ")", 99, OperatorData::LEFT, false ); \
DECLARE_OP( openSqBrac, "[", 100, OperatorData::BOTH, false ); \
DECLARE_OP( closeSqBrac,"]", 99, OperatorData::LEFT, false ); \
DECLARE_OP( openCrBrac, "{", 100, OperatorData::RIGHT, false ); \
DECLARE_OP( closeCrBrac,"}", 99, OperatorData::LEFT, false ); \
ALL_OPS;
// for read only, dont screw with this
unordered_map<string, Operator>& getOpsMap() {return opsMap;}
// returns if the given operator is an opening bracket or peren
bool isOpenBrac(Operator op);
bool isCloseBrac(Operator op);
private:
// is only called in init
AllOperators();
// used internally by the constructor
void putOpInMap(Operator op);
// a hash map of all the operators
unordered_map<string, Operator> opsMap;
};
// the single instance of this class, starts out as nullptr but chages to a real instance in AllOperators::init
//extern shared_ptr<AllOperators> ops;
extern AllOperators* ops;
================================================
FILE: h/AstNode.h
================================================
#pragma once
#include "Token.h"
#include "Action.h"
#include "ErrorHandler.h"
class NamespaceData;
typedef shared_ptr<NamespaceData> Namespace;
#include <vector>
using std::vector;
class AstNodeBase;
typedef unique_ptr<AstNodeBase> AstNode;
AstNode astNodeFromTokens(const vector<Token>& tokens, int left, int right);
class AstNodeBase
{
public:
virtual ~AstNodeBase() = default;
void setInput(Namespace nsIn, bool dynamicIn, Type left, Type right)
{
if (inputHasBeenSet)
{
throw PineconeError("tried to set input on an AST node '"+getString()+"' more then once", INTERNAL_ERROR, getToken());
}
inputHasBeenSet=true;
ns=nsIn;
dynamic=dynamicIn;
inLeftType=left;
inRightType=right;
}
virtual bool isVoid() {return false;}
virtual bool isType() {return false;}
virtual bool isFunctionWithOutput() {return false;}
/*
Type getInLeftType()
{
if (!inputHasBeenSet)
throw PineconeError("tried to get inLeftType before input was set", INTERNAL_ERROR, getToken());
return inLeftType;
}
Type getInRightType()
{
if (!inputHasBeenSet)
throw PineconeError("tried to get inRightType before input was set", INTERNAL_ERROR, getToken());
return inRightType;
}
*/
virtual string getString()=0;
virtual AstNode makeCopy(bool copyCache)=0; // if copyCache is false, input and actions will not be copied
virtual bool canBeWhatev() {return false;}
// returns nullptr if it can't do it
virtual AstNode makeCopyWithSpecificTypes(Type leftInType, Type rightInType) {return nullptr;}
Type getReturnType()
{
if (!returnType)
{
if (!inputHasBeenSet)
{
throw PineconeError("tried to get return type from AST node when input had not been set", INTERNAL_ERROR, getToken());
}
resolveReturnType();
}
if (!returnType)
{
throw PineconeError("AST node "+getString()+"failed to supply a return type", INTERNAL_ERROR);
}
return returnType;
}
Action getAction()
{
if (!action)
{
if (!ns)
{
throw PineconeError("tried to get action from AST node when input had not been set", INTERNAL_ERROR, getToken());
}
resolveAction();
if (!nameHint.empty())
action->nameHint=nameHint;
}
return action;
}
void dealWithConstants()
{
if (!ns)
{
throw PineconeError("tried to deal with constants before input was set", INTERNAL_ERROR, getToken());
}
resolveConstant();
}
// primarily used for error throwing, can return null
virtual Token getToken()=0;
string nameHint="";
virtual void nameHintSet() {}
protected:
AstNodeBase() {}
void copyToNode(AstNodeBase* other, bool copyCache);
virtual void resolveReturnType()
{
returnType=getAction()->getReturnType();
}
virtual void resolveAction()=0;
virtual void resolveConstant() {};
Type inLeftType=nullptr, inRightType=nullptr;
Action action=nullptr;
Type returnType=nullptr;
bool dynamic=false;
Namespace ns=nullptr;
bool inputHasBeenSet=false;
};
class AstVoid: public AstNodeBase
{
public:
static unique_ptr<AstVoid> make() {return unique_ptr<AstVoid>(new AstVoid);}
bool isVoid() {return true;}
string getString() {return "void node";}
AstNode makeCopy(bool copyCache)
{
auto out=new AstVoid;
copyToNode(out, copyCache);
return AstNode(out);
}
void resolveReturnType() {returnType=Void;}
void resolveAction()
{
if (!inLeftType->isVoid() || !inRightType->isVoid())
{
throw PineconeError("AstVoid given non void input", INTERNAL_ERROR, getToken());
}
action=voidAction;
}
Token getToken() {return nullptr;}
};
//extern AstNode astVoid;
class AstList: public AstNodeBase
{
public:
// make a new instance of this type of node
static unique_ptr<AstList> make(vector<AstNode>& in)
{
unique_ptr<AstList> node(new AstList);
node->nodes=move(in);
return node;
}
string getString();
AstNode makeCopy(bool copyCache)
{
auto out=new AstList;
copyToNode(out, copyCache);
for (int i=0; i<(int)nodes.size(); i++)
{
out->nodes.push_back(nodes[i]->makeCopy(copyCache));
}
return AstNode(out);
}
//void resolveReturnType();
void resolveAction();
Token getToken() {return nodes.empty()?nullptr:nodes[0]->getToken();}
private:
// the list of sub nodes
vector<AstNode> nodes;
};
class AstConstExpression;
class AstToken: public AstNodeBase
{
public:
static unique_ptr<AstToken> make(Token tokenIn)
{
unique_ptr<AstToken> node(new AstToken);
node->token=tokenIn;
return node;
}
string getString();
AstNode makeCopy(bool copyCache)
{
auto out=new AstToken;
copyToNode(out, copyCache);
out->token=token;
return AstNode(out);
}
void resolveAction();
Token getToken() {return token;}
private:
friend AstConstExpression;
Token token=nullptr;
};
class AstFuncBody: public AstNodeBase
{
public:
static AstNode make(AstNode leftTypeIn, AstNode rightTypeIn, AstNode returnTypeIn, AstNode bodyIn)
{
auto node=new AstFuncBody();
if (!leftTypeIn->isType() || !rightTypeIn->isType() || !returnTypeIn->isType())
{
throw PineconeError("AstFuncBody made with function input nodes that are not types", INTERNAL_ERROR);
}
node->leftTypeNode=move(leftTypeIn);
node->rightTypeNode=move(rightTypeIn);
node->returnTypeNode=move(returnTypeIn);
node->bodyNode=move(bodyIn);
return AstNode(node);
}
string getString();
AstNode makeCopy(bool copyCache)
{
auto out=new AstFuncBody;
copyToNode(out, copyCache);
out->leftTypeNode=leftTypeNode->makeCopy(copyCache);
out->rightTypeNode=rightTypeNode->makeCopy(copyCache);
out->returnTypeNode=returnTypeNode->makeCopy(copyCache);
out->bodyNode=bodyNode->makeCopy(copyCache);
out->typesInputSet=typesInputSet;
return AstNode(out);
}
void resolveAction();
AstNode makeCopyWithSpecificTypes(Type leftInType, Type rightInType);
Token getToken() {return bodyNode->getToken();}
void setTypesInput()
{
if (!typesInputSet)
{
leftTypeNode->setInput(ns, false, Void, Void);
rightTypeNode->setInput(ns, false, Void, Void);
returnTypeNode->setInput(ns, false, Void, Void);
typesInputSet=true;
}
}
bool canBeWhatev()
{
setTypesInput();
return
leftTypeNode->getReturnType()->isWhatev() ||
rightTypeNode->getReturnType()->isWhatev() ||
returnTypeNode->getReturnType()->isWhatev();
}
AstNode leftTypeNode, rightTypeNode, returnTypeNode, bodyNode;
bool typesInputSet=false;
};
class AstExpression: public AstNodeBase
{
public:
static unique_ptr<AstExpression> make(AstNode leftInIn, AstNode centerIn, AstNode rightInIn)
{
unique_ptr<AstExpression> node(new AstExpression);
node->leftIn=move(leftInIn);
node->center=move(centerIn);
node->rightIn=move(rightInIn);
return node;
}
//bool isType() {return leftIn->isType() || rightIn->isType();}
AstNode makeCopy(bool copyCache)
{
auto out=new AstExpression;
copyToNode(out, copyCache);
out->leftIn=leftIn->makeCopy(copyCache);
out->center=center->makeCopy(copyCache);
out->rightIn=rightIn->makeCopy(copyCache);
return AstNode(out);
}
string getString();
void resolveAction();
Token getToken() {return center->getToken();}
AstNode leftIn=nullptr, center=nullptr, rightIn=nullptr;
};
class AstConstExpression: public AstNodeBase
{
public:
static unique_ptr<AstConstExpression> make(unique_ptr<AstToken> centerIn, AstNode rightInIn)
{
unique_ptr<AstConstExpression> node(new AstConstExpression);
//node->leftIn=move(leftInIn);
node->center=move(centerIn);
node->rightIn=move(rightInIn);
return node;
}
string getString();
AstNode makeCopy(bool copyCache)
{
auto out=new AstConstExpression;
copyToNode(out, copyCache);
out->center=unique_ptr<AstToken>((AstToken*)center->makeCopy(copyCache).release());;
out->rightIn=center->makeCopy(copyCache);
return AstNode(out);
}
void resolveConstant();
void resolveAction() {action=voidAction;};
Token getToken() {return center->getToken();}
private:
//AstNode leftIn=nullptr;
unique_ptr<AstToken> center=nullptr;
AstNode rightIn=nullptr;
};
class AstOpWithInput: public AstNodeBase
{
public:
static unique_ptr<AstOpWithInput> make(vector<AstNode>& leftInIn, Token tokenIn, vector<AstNode>& rightInIn)
{
unique_ptr<AstOpWithInput> node(new AstOpWithInput);
node->leftIn=move(leftInIn);
node->token=tokenIn;
node->rightIn=move(rightInIn);
return node;
}
bool isFunctionWithOutput();
string getString();
AstNode makeCopy(bool copyCache)
{
auto out=new AstOpWithInput;
copyToNode(out, copyCache);
out->token=token;
for (int i=0; i<(int)leftIn.size(); i++)
{
out->leftIn.push_back(leftIn[i]->makeCopy(copyCache));
}
for (int i=0; i<(int)rightIn.size(); i++)
{
out->rightIn.push_back(rightIn[i]->makeCopy(copyCache));
}
return AstNode(out);
}
void resolveAction();
Token getToken() {return token;}
Token token=nullptr;
vector<AstNode> leftIn, rightIn;
};
class AstTuple: public AstNodeBase
{
public:
// make a new instance of this type of node
static unique_ptr<AstTuple> make(vector<AstNode>& in)
{
unique_ptr<AstTuple> node(new AstTuple);
node->nodes=move(in);
return node;
}
string getString();
AstNode makeCopy(bool copyCache)
{
auto out=new AstTuple;
copyToNode(out, copyCache);
for (int i=0; i<(int)nodes.size(); i++)
{
out->nodes.push_back(nodes[i]->makeCopy(copyCache));
}
return AstNode(out);
}
//void resolveReturnType();
void resolveAction();
Token getToken() {return nodes.empty()?nullptr:nodes[0]->getToken();}
private:
vector<AstNode> nodes;
};
class AstType: public AstNodeBase
{
public:
bool isType() {return true;}
void resolveAction()
{
throw PineconeError("AstType::resolveAction called, which it shouldn't have been", INTERNAL_ERROR, getToken());
}
};
class AstTypeType: public AstType
{
public:
static unique_ptr<AstTypeType> make(Type typeIn)
{
unique_ptr<AstTypeType> node(new AstTypeType);
node->returnTypeNotMeta=typeIn;
return node;
}
string getString()
{
return returnType->getString();
}
AstNode makeCopy(bool copyCache)
{
auto out=new AstTypeType;
copyToNode(out, copyCache);
out->returnType=returnType;
return AstNode(out);
}
void resolveReturnType()
{
returnType=returnTypeNotMeta->getMeta();
}
void nameHintSet()
{
if (!nameHint.empty() && returnTypeNotMeta->nameHint.empty())
returnTypeNotMeta->nameHint=nameHint;
}
Token getToken() {return nullptr;}
private:
Type returnTypeNotMeta;
};
class AstVoidType: public AstType
{
public:
static unique_ptr<AstVoidType> make()
{
unique_ptr<AstVoidType> node(new AstVoidType);
return node;
}
string getString() {return "{}";}
AstNode makeCopy(bool copyCache)
{
auto out=new AstVoidType;
copyToNode(out, copyCache);
return AstNode(out);
}
void resolveReturnType()
{
returnType=Void->getMeta();
}
Token getToken() {return nullptr;}
private:
};
class AstTokenType: public AstType
{
public:
static unique_ptr<AstTokenType> make(Token tokenIn)
{
unique_ptr<AstTokenType> node(new AstTokenType);
node->token=tokenIn;
return node;
}
string getString();
AstNode makeCopy(bool copyCache)
{
auto out=new AstTokenType;
copyToNode(out, copyCache);
out->token=token;
return AstNode(out);
}
void resolveReturnType();
Token getToken() {return token;}
private:
Token token=nullptr;
};
class AstTupleType: public AstType
{
public:
struct NamedType
{
Token name; // can be null
unique_ptr<AstType> type;
};
static unique_ptr<AstTupleType> make(vector<NamedType>& in)
{
unique_ptr<AstTupleType> node(new AstTupleType);
node->subTypes=move(in);
return node;
}
string getString();
AstNode makeCopy(bool copyCache)
{
auto out=new AstTupleType;
copyToNode(out, copyCache);
for (int i=0; i<(int)subTypes.size(); i++)
{
out->subTypes.push_back({subTypes[i].name, unique_ptr<AstType>((AstType*)subTypes[i].type->makeCopy(copyCache).release())});
}
return AstNode(out);
}
void resolveReturnType();
Token getToken() {return subTypes.empty()?nullptr:subTypes[0].name;}
private:
vector<NamedType> subTypes;
};
class AstActionWrapper: public AstNodeBase
{
public:
static unique_ptr<AstActionWrapper> make(Action actionIn) {
auto out = unique_ptr<AstActionWrapper>(new AstActionWrapper);
out->inLeftType=actionIn->getInLeftType();
out->inRightType=actionIn->getInRightType();
out->returnType=actionIn->getReturnType();
out->action=actionIn;
out->dynamic=true; // shouldn't matter
out->ns=nullptr; // shouldn't matter
out->inputHasBeenSet=true;
return out;
}
string getString() {return "action wrapper node";}
AstNode makeCopy(bool copyCache)
{
auto out=new AstActionWrapper;
copyToNode(out, true);
return AstNode(out);
}
void resolveAction()
{
throw PineconeError("AstActionWrapper::resolveAction called, which it shouldn't have been", INTERNAL_ERROR);
}
Token getToken() {return nullptr;}
};
class AstWhatevToActionFactory: public AstNodeBase
{
public:
static AstNode make(function<Action(Type left, Type right)> lambda)
{
auto node=new AstWhatevToActionFactory();
node->lambda=lambda;
return AstNode(node);
}
string getString() {return "AstWhatevToActionFactory";}
AstNode makeCopy(bool copyCache)
{
auto out=new AstWhatevToActionFactory;
copyToNode(out, copyCache);
out->lambda=lambda;
return AstNode(out);
}
void resolveAction() {throw PineconeError("AstWhatevToActionFactory::resolveAction called, wich should never happen", INTERNAL_ERROR);}
AstNode makeCopyWithSpecificTypes(Type leftInType, Type rightInType)
{
auto action=lambda(leftInType, rightInType);
if (action)
return AstActionWrapper::make(action);
else
return nullptr;
}
Token getToken() {return nullptr;}
bool canBeWhatev() {return true;}
private:
function<Action(Type leftInType, Type rightInType)> lambda;
};
================================================
FILE: h/CppProgram.h
================================================
#pragma once
#include "Type.h"
#include <map>
#include <unordered_set>
// Pinecone names that are hardcoded should start with '-' so that collisions can't happen with input code
/* naming conventions for hardcoded Pineocne name prefixes
these go in frount of any names that are hardcoded for the transpiler, since they are not valid identifier
cars they can not collide with names from pn source and they will be removed before they get to C++ source
global funcs: $
global vars: *
local vars: -
types: surounded by {}
*/
class CppNameContainer
{
public:
static shared_ptr<CppNameContainer> makeRoot();
shared_ptr<CppNameContainer> makeChild();
void addPn(const string& pn, const string& cppNameHint="<- the value of that pn string please"); // will throw an error if pnName already exists
void reserveCpp(const string& cpp, bool ignoreCollisions=false);
bool hasPn(const string& pn);
string getCpp(const string& pn); // will throw an error if the Pinecone name doesn't exist
CppNameContainer* getParent() {return parent;}
private:
bool hasPnMe(const string& pn);
CppNameContainer();
bool hasCpp(const string& cpp);
bool hasCppMe(const string& cpp);
bool hasCppUp(const string& cpp);
bool hasCppDown(const string& cpp);
std::unordered_set<string> cppSet;
std::map<string, string> pnToCppMap;
CppNameContainer* parent=nullptr;
vector<shared_ptr<CppNameContainer>> children;
};
class CppFuncBase
{
public:
CppFuncBase(string prototypeIn, shared_ptr<CppNameContainer> myNames, bool returnsValIn);
void code(const string& in);
void name(const string& in); // converts a Pinecone name to a posibly different C++ name
void line(const string& in);
void endln();
void comment(const string& in);
void pushExpr();
void popExpr();
void pushBlock();
void popBlock();
string pnToCpp(const string& in);
int getExprLevel() {return exprLevel;}
bool getIfFreshLine() {return freshLine;}
int getBlockLevel() {return blockLevel;}
bool getIfReturnsVal() {return returnsVal;}
string getSource() {return source;}
string getPrototype() {return prototype;}
private:
string indent="\t";
bool freshLine=true;
int blockLevel=0;
int exprLevel=0;
string varDeclareSource;
string source;
string prototype;
bool returnsVal=false;
bool fakeStartBlock=false;
vector<shared_ptr<CppNameContainer>> namespaceStack;
friend CppProgram;
};
typedef shared_ptr<CppFuncBase> CppFunc;
class CppProgram
{
public:
CppProgram();
void code(const string& in) {activeFunc->code(in);}
void name(const string& in) {activeFunc->name(in);}
void line(const string& in) {activeFunc->line(in);}
void endln() {activeFunc->endln();}
void comment(const string& in) {activeFunc->comment(in);}
void pushExpr() {activeFunc->pushExpr();}
void popExpr() {activeFunc->popExpr();}
void pushBlock() {activeFunc->pushBlock();}
void popBlock() {activeFunc->popBlock();}
string pnToCpp(const string& in){return activeFunc->pnToCpp(in);}
int getExprLevel() {return activeFunc->getExprLevel();}
int getBlockLevel() {return activeFunc->getBlockLevel();}
int getIfReturnsVal() {return activeFunc->getIfReturnsVal();}
void setup();
string getTypeCode(Type in);
void declareVar(const string& nameIn, Type typeIn, string initialValue="");
void declareGlobal(const string& nameIn, Type typeIn, string initialValue="");
void addHeadCode(const string& code);
bool hasFunc(const string& name);
void addFunc(const string& name, vector<std::pair<string, string>> args, string returnType, string contents);
void pushFunc(const string& name, const string& cppNameHint, Type leftIn, Type rightIn, Type returnType);
void pushFunc(const string& name, Type leftIn, Type rightIn, Type returnType) {pushFunc(name, name, leftIn, rightIn, returnType);}
//void pushFunc(const string&, vector<NamedType> args, Type returnType);
void popFunc();
bool isMain() {return funcStack.size()==1;}
string getCppCode();
shared_ptr<CppNameContainer> getGlobalNames() {return globalNames;};
private:
string indent="\t";
string globalTopCode;
string globalIncludesCode;
string globalVarCode;
string globalTypesCode;
CppFunc activeFunc;
vector<string> funcStack;
std::map<string, CppFunc> funcs;
shared_ptr<CppNameContainer> globalNames;
};
void addToProgPnStr(CppProgram * prog);
================================================
FILE: h/ErrorHandler.h
================================================
#pragma once
#include "Token.h"
#include <string>
using std::string;
#define FUNC string(__FUNCTION__)
//#define FUNC string(__PRETTY_FUNCTION__) //like __FUNCTION__, but adds class name
enum ErrorPriority
{
SOURCE_ERROR,
SOURCE_WARNING,
JSYK,
INTERNAL_ERROR,
RUNTIME_ERROR
};
class ErrorHandler
{
public:
static string priorityToStr(ErrorPriority in);
void log(string msg, ErrorPriority priority, Token token=nullptr);
void msg(string in);
bool getIfErrorLogged() {return errorHasBeenLogged;}
private:
bool errorHasBeenLogged=false;
};
extern ErrorHandler error;
class PineconeError
{
public:
PineconeError(string msgIn, ErrorPriority priorityIn, Token tokenIn=nullptr);
void log();
private:
string msg;
ErrorPriority priority;
Token token;
};
//typedef shared_ptr<PineconeError> Err;
//Err makeError(string msgIn, ErrorPriority priorityIn, Token tokenIn=nullptr) {return Err(new PineconeError(msgIn, priorityIn, tokenIn));}
================================================
FILE: h/Namespace.h
================================================
#pragma once
#include "Type.h"
#include "Action.h"
#include "Token.h"
#include "Operator.h"
#include "AstNode.h"
#include <unordered_map>
using std::unordered_map;
#include <vector>
using std::vector;
class StackFrame;
class NamespaceData;
typedef shared_ptr<NamespaceData> Namespace;
/// has a bunch of hash tables for all the identifiers in a single scope
// contains a pointer to a stack frame but there may be many namespaces (due to many scopes) in a single stack frame
// for example, a function has a single stack frame but has several if blocks, each with its own NamespaceData
// each NamespaceData also has a pointer to its parent, which should only be null for the global standard library
// contains a pointer to its parent namespace, which can be null if it is the root
// can be created with one of the 'make' functions, not by directly instantiating it
class NamespaceData: public std::enable_shared_from_this<NamespaceData>
{
public:
// makes a namespace with no parents and a new stack frame
static Namespace makeRootNamespace();
// makes a child namespace with the same stack frame as this one
Namespace makeChild();
// makes a child namespace with a new stack frame
Namespace makeChildAndFrame(string nameIn);
// returns a string with the complete contents of this namespace
string getString();
// retuens a string with this namespace and all it's parents nicely formatted
string getStringWithParents();
//Namespace getParent() {return parent;}
shared_ptr<StackFrame> getStackFrame() {return stackFrame;}
void setInput(Type left, Type right);
void addNode(AstNode node, string id);
// recursivly searches up looking for a type of the given name
// returns UnknownType if it cant find the requested type
Type getType(string name, bool throwSourceError, Token tokenForError);
// returns the destructor of the given type, or nullptr if there isn't one
Action getDestroyer(Type type);
// returns the copier of the given type, or nullptr if there isn't one
Action getCopier(Type type);
// returns an action that takes the input types
// on error, it will throw a source error if throwSourceError is true. otherwise, it will return nullptr
Action getActionForTokenWithInput(Token token, Type left, Type right, bool dynamic, bool throwSourceError, Token tokenForError);
vector<Action>* getDestroyerActions() {return &destructorActions;}
Action wrapInDestroyer(Action in);
private:
// retrieve all nodes in the given catagories with the given names from this namespace and all its parents
void getNodes(vector<AstNodeBase*>& out, string text, bool checkActions, bool checkDynamic, bool checkWhatev);
void nodesToMatchingActions(vector<Action>& out, vector<AstNodeBase*>& nodes, Type leftInType, Type rightInType);
class IdMap
{
public:
void add(string key, AstNode node);
void get(string key, vector<AstNodeBase*>& out);
private:
unordered_map<string, vector<AstNode>> nodes;
};
// add a get and set action for a variable also adds its data to the stack frame
Action addVar(Type type, string name);
// the only constructor, is private so use a make function instead
NamespaceData(Namespace parentIn, shared_ptr<StackFrame> stackFrameIn, string nameIn="");
// the name of this namespace, for debugging purposes only
string myName;
// this namespaces parent
shared_ptr<NamespaceData> parent;
// the stack frame this namespace uses
// does not have a reference back because there can be many namespaces in one stack frame
shared_ptr<StackFrame> stackFrame;
// contains all actions that can be used anywhere, and don't rely on dynamic content like variables
IdMap actions;
// contains actions that use runtime data, like variables
IdMap dynamicActions;
// contains actions that use a whatev type
IdMap whatevActions;
// contains all types in this namespace
IdMap types;
// contains destructors for types, the key string is a pointer to the type fed through ptrToUniqueStr with 6 digits
//IdMap destructors;
// like destructors, but for making copies
//IdMap copiers;
vector<Action> destructorActions;
};
================================================
FILE: h/Operator.h
================================================
#pragma once
class TokenData;
#include <memory>
using std::shared_ptr;
#include <string>
using std::string;
class AllOperators;
// describes an operator
// NOTE: there will only be one instance of OperatorData for +, not one for every overload of +
class OperatorData
{
public:
enum InputTaken
{
LEFT,
RIGHT,
BOTH,
};
string getText() {return text;}
int getPrecedence() {return precedence;}
bool isOverloadable() {return overloadable;}
bool takesLeftInput() {return input==BOTH || input==LEFT;}
bool takesRightInput() {return input==BOTH || input==RIGHT;}
private:
friend AllOperators;
OperatorData(string textIn, int precedenceIn, InputTaken inputIn, bool overloadableIn)
{
text=textIn;
precedence=precedenceIn;
input=inputIn;
overloadable=overloadableIn;
}
// the text of the operator, generally 1 or 2 characters
string text;
// the precedence of left and right inputs, if this is 0 then the operator does not take an input on that side
// if even then precedence level is parced left to right. if odd then right to left
int precedence;
// if this operator can be overloaded
bool overloadable;
// if this operator takes input from the left, right or both
InputTaken input;
};
typedef shared_ptr<OperatorData> Operator;
================================================
FILE: h/PineconeProgram.h
================================================
#pragma once
#include "VERSION.h"
#include <string>
#include <iostream>
#include <math.h>
#include <vector>
#include <list>
using std::max;
using std::min;
using std::cout;
using std::endl;
using std::string;
using std::to_string;
using std::vector;
using std::list;
#include "msclStringFuncs.h"
#include "Namespace.h"
#include "StackFrame.h"
#include "Token.h"
#include "AstNode.h"
#include "SourceFile.h"
extern vector<string> cmdLineArgs;
class Element;
class PineconeProgram
{
public:
PineconeProgram();
~PineconeProgram() {cleanUp();}
string getCpp();
void resolveProgram(string inFilename, bool printExtraOutput);
Namespace getGlobalActionTable();
void execute();
private:
void cleanUp();
private:
shared_ptr<SourceFile> file=nullptr;
//a list of all the tokens in the program
vector<Token> tokens;
//root of the abstract syntax tree
AstNode astRoot=nullptr;
//root of the action tree
Action actionRoot=createNewVoidAction();
vector<char> whitespaceChars, letterChars, digitChars;
char singleLineComment;
};
================================================
FILE: h/SourceFile.h
================================================
#pragma once
#include <string>
using std::string;
class SourceFile
{
public:
SourceFile()
{
filename="[empty_file]";
contents="";
}
SourceFile(string filenameIn, bool printOutput);
string getFilename() {return filename;}
// get the path to the directory this file is in
string getDirPath();
const string& getContents() {return contents;}
string getBoxedString();
string getLine(int lineNum);
inline int size()
{
return contents.size();
}
inline char operator[](int i)
{
return contents[i];
}
inline string substr(size_t start, size_t len)
{
return contents.substr(start, len);
}
private:
string filename;
string contents;
};
================================================
FILE: h/StackFrame.h
================================================
#pragma once
#include <vector>
using std::vector;
#include "Type.h"
//#include "Action.h"
extern void* globalFramePtr;
extern void* stackPtr;
class StackFrame
{
public:
void addMember(Type in);
// set the left and right input types (can only be done once)
void setInput(Type left, Type right);
size_t getSize() {return frameSize;}
Type getLeftInType();
Type getRightInType();
size_t getLeftOffset();
size_t getRightOffset();
private:
//Action actions; //must always be functionAction
vector<Type> members;
size_t frameSize=0;
bool inputSet=false;
int leftInputIndex=-1;
int rightInputIndex=-1;
size_t leftInputOffset;
size_t rightInputOffset;
};
================================================
FILE: h/Token.h
================================================
#pragma once
#include "Operator.h"
#include <string>
using std::string;
#include <vector>
using std::vector;
class SourceFile;
//represents a single token such as an Int literal, an operator, or an identifier
//is immutable
class TokenData
{
public:
enum Type
{
WHITESPACE,
LINE_END,
IDENTIFIER,
LITERAL,
STRING_LITERAL,
OPERATOR,
LINE_COMMENT,
BLOCK_COMMENT,
SCOPE,
CAST,
TUPLE,
UNKNOWN
};
TokenData(string textIn, shared_ptr<SourceFile> fileIn, int lineIn, int charPosIn, Type tokenTypeIn, Operator opIn=Operator(nullptr))
{
text=textIn;
file=fileIn;
line=lineIn;
charPos=charPosIn;
tokenType=tokenTypeIn;
op=opIn;
}
string getText() const {return text;}
shared_ptr<SourceFile> getFile() const {return file;}
int getLine() const {return line;}
int getCharPos() const {return charPos;}
TokenData::Type getType() const {return tokenType;}
Operator getOp() const {return op;}
bool isComment() {return tokenType==LINE_COMMENT || tokenType==BLOCK_COMMENT;}
static string typeToString(TokenData::Type in);
string getDescription();
string getTypeDescription();
private:
string text;
shared_ptr<SourceFile> file;
int line;
int charPos;
Type tokenType;
Operator op;
};
typedef shared_ptr<TokenData> Token;
Token makeToken(string textIn, shared_ptr<SourceFile> fileIn, int lineIn, int charPosIn, TokenData::Type tokenTypeIn, Operator opIn=Operator(nullptr));
Token makeToken(string textIn);
string stringFromTokens(const vector<Token>& tokens, int left, int right);
string tableStringFromTokens(const vector<Token>& tokens, string tableName);
================================================
FILE: h/Type.h
================================================
#pragma once
#include <string>
using std::string;
#include <vector>
using std::vector;
#include <memory>
using std::shared_ptr;
using std::unique_ptr;
#include <cstring>
using std::memcpy;
class TypeBase;
typedef shared_ptr<TypeBase> Type;
const extern Type Unknown;
const extern Type Whatev;
const extern Type Void;
const extern Type Bool;
const extern Type Byte;
const extern Type Int;
const extern Type Dub;
extern Type String;
class CppProgram;
class ActionData;
struct NamedType
{
string name;
Type type;
};
struct OffsetAndType
{
size_t offset;
Type type;
};
class TypeBase: public std::enable_shared_from_this<TypeBase>
{
public:
virtual ~TypeBase() = default;
///steps to adding a new type (these may be old):
/// 1. Add to the enum
/// 2. add it to toString in Type.cpp
/// 3. add it to isCreatable in Type.cpp
/// 4. if it has a literal, add a class for that in LiteralElement.h
/// 5. add the creation of said literal to LiteralElement::makeNew in LiteralElement.cpp
/// 6. you may have to add logic to initialProgramPopulation or getElementType to correctly capture the section of source containing your type literal
/// 7. add a class to DataElem.h
/// 8. add it to makeNewOfType in DataElem.cpp
enum PrimitiveType
{
UNKNOWN ,
VOID ,
BYTE,
DUB,
INT,
PTR,
BOOL,
TUPLE,
WHATEV,
METATYPE,
};
/* type compact forms
Void: v
Unknown: u
Bool: b
Byte: y
Int: i
Dub: d
Ptr: Pp_..._pP
Tuple: Tt_[size of name]_name_type..._tT
Whatev: W
Meta: Mm_..._mM
*/
static Type makeNewVoid();
static Type makeNewPrimitive(PrimitiveType typeIn);
static Type makeNewWhatev();
//static Type makeNew(unordered_map<string, Type>, string nameIn);
//TypeBase(string nameIn) {name=nameIn;}
Type getMeta();
Type getPtr();
virtual Type actuallyIs(Type target); // returns a type with with the whatevs resolved with the target type
static string getString(PrimitiveType in);
virtual string getString()=0;
string getName() {return nameHint.empty()?getCompactString():nameHint;}
virtual string getCompactString()=0; // returns a string that is unique, only shared with other types that match this one
virtual string getCppLiteral(void * data, CppProgram * prog)=0;
virtual bool isCreatable() {return true;};
virtual bool isVoid() {return false;};
virtual bool isWhatev() {return false;};
virtual size_t getSize()=0;
//string getName() {return name;}
virtual PrimitiveType getType()=0;
bool matches(Type other);
virtual Type getSubType() {return Void;}
virtual OffsetAndType getSubType(string name) {return {0, nullptr};}
virtual vector<NamedType>* getAllSubTypes(); // will thow an error if this is not a tuple type
// void setNameHint(const string& in) {if (nameHint.empty()) nameHint=in;} // only sets name hint on any type once, after that it fails quietly
// string getNameHint
string nameHint=""; // not reliable, will often be ""; should only be used as a hint, not depended on
protected:
virtual bool matchesSameTypeType(Type other)=0;
Type ptrToMe=nullptr;
};
Type makeTuple(const vector<NamedType>& in, bool isAnonymous);
// since types are immutable, this class is an easy way to construct a tuple type
class TupleTypeMaker
{
public:
TupleTypeMaker();
void add(string name, Type type);
void add(Type type);
Type get(bool isAnonymous);
private:
string getUniqueName();
std::unique_ptr<vector<NamedType>> subTypes;
};
================================================
FILE: h/VERSION.h
================================================
#pragma once
// the version of pinecone is vX.Y.Y
const int VERSION_X=0;
const int VERSION_Y=5;
const int VERSION_Z=1;
================================================
FILE: h/msclStringFuncs.h
================================================
#pragma once
#include "PineconeProgram.h"
#include <string>
using std::string;
using std::to_string;
#include <vector>
using std::vector;
#include <functional>
using std::string;
#include "utils/stringUtils.h"
// returns if the substring matches the input
// nothing needed for unicode
// in: the string to check against
// pos: the location in 'in' to line the start of the substring up with
// subStr: the string to compare with
// returns: if the substring matches the input at the given location
bool substringMatches(const string& in, int pos, const string& subStr);
// returns the location of a pattern in a string, or -1 if it can't find it
// no unicode support yet
// in: the string to search
// startPos: where to start looking (inclusive)
// pattern: the single or multi character pattern to search for, wildcards are not yet supported
// returns: the absolute position (not the offset) of the first instance of the pattern in the input, or -1 if it can't find it
int searchInString(const string& in, const string& pattern, int startPos=0);
// replaces all instances of one substring with another
// in: the string to search
// searchFor: pattern to replace
// replaceWith: new value
// returns: in after replace operation
string replaceSubstring(const string& in, const string& searchFor, const string& replaceWith);
// sets the given array to be the given string sliced up using the given pattern
// in: the string to slice
// pattern: the pattern used to chop up the string, will not be included in output
// out: all the substrings will be appended to this
void sliceStringBy(const string& in, const string& pattern, vector<string>& out);
// indents a string
// in: the string to indent (can be multi line)
// indent: the string to use as the indent
// returns: the string indented
string indentString(const string& in, string indent=" ", int level=1);
// returns the original string with the tabs replaced by the correct number of spaces
// in: the string to convert
// spaceNum: number of spaces per tab
// returns: a string with the tabs replaced by spaces
string tabsToSpaces(const string& in, int spaceNum=4);
// runs tabsToSpaces on an entire array of strings
void tabsToSpaces(vector<string>& in);
// returns the original string but padded with the given padding string
// in: the string to pad
// size: the size of the output string
// alignment:
// 1: left
// -1: right
// 0: center
// pad: the string to use for padding (assumes this string is one char long)
// leftCap: a string to put on the left size of the input (inside the padding) that will not get chopped
// rightCap: a string to put on the right size of the input (inside the padding) that will not get chopped
// returns: the padded string, or the chopped string if the input is shorter then the size
string padString(const string& in, int size, int alignment=1, string pad=" ", string leftCap="", string rightCap="");
// returns the specific line (starting at 1) in the string it is sent
// in: the (presumably multiline) string
// lineNum: the line to return
// returns: the specific line (without newlines), or an empty string if that line is invalid
string getTextOfLine(const string& in, int lineNum);
// takes an array of lines and puts a box around it
// in: an array of strings, each which will be on a new line
// boxName: the name of the box
// lineNum: the offset of line numbers, no line nums will be displayed if -1
// alwaysWidthMax: if to always use the max width
// maxWidth: the max width of a line, will be truncated if longer
// returns: a string with a box around the content (must be displayed in monospace obviously)
string lineListToBoxedString(const vector<string>& in, string boxName="", int lineNum=-1, bool alwaysWidthMax=false, int maxWidth=-1);
// puts the contents of a string into a well formatted
// in: the input stringz
// boxName: the name that will appear at the top of the box
// showLineNums: if to show line numbers
// alwaysWidthMax: if to always use the max width
// maxWidth: 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
// returns: the boxed string
string putStringInBox(const string& in, string boxName="", bool showLineNums=false, bool alwaysWidthMax=false, int maxWidth=-1);
// puts the contents of a string into a table, with tabs being verticle seporators and newlines being horizontle ones
// in: the input string
// tableName: the name that will apear at the top of the table
// returns: a string that looks like a table
string putStringInTable(const string& in, string tableName);
// assembles one section of a tree
string assembleTreeString(const string& root, vector<string>& leaves);
// converts a double to a string, with always at least one zero before and after the decimal
string doubleToString(double in);
int stringToInt(string in);
double stringToDouble(string in);
// load entire file and return its contents
// inName: the path to the file to open
// debug: if to print status several times to stdout
// returns: the contents of the file, or an empty string if there is an error
string loadEntireFile(string inName, bool debug=false);
bool writeFile(const string& filename, const string& contents, bool debug=false);
// returns a random character that can be an upper case letter, a lower case letter or a digit
char getRandChar();
// given a hint name and a function to check if a name is unique, returns a unique string
// checker should return true if the given name IS valid
// if alwaysAppendRandom, it will always append a number of random digits
string getUniqueString(string hint, std::function<bool (string)> checker, bool alwaysAppendRandom=false);
// run a shell command and return the output
// cmd: the command to run
// returns: the output of the command
string runCmd(string cmd, bool printOutput=false);
// get width of the current terminal
// returns: width of the terminal
int getTermWidth();
================================================
FILE: h/utils/fileUtils.h
================================================
#pragma once
#include "stringUtils.h"
void loadFile(string filepath, string& contents);
void writeFile(string filepath, const string& contents);
================================================
FILE: h/utils/stringArray.h
================================================
#pragma once
#include "stringUtils.h"
namespace str
{
void splitBy(vector<string>& out, const string& in, const string& splitter, bool keepSplitter=false);
//void splitBy(vector<string>& out, const string& in, vector<string>& splitters, bool keepSplitter=false);
inline void splitByLine(vector<string>& out, const string& in);
int getMaxWidth(vector<string>& in);
// if size is -1 then it is determined as the max width of all the elements in out
void padWidths(vector<string>& out, int size=-1, StringPadAlignment alignment=ALIGNMENT_LEFT, string pad=" ", string leftCap="", string rightCap="");
string join(vector<string>& in, string joiner="\n", bool addAtEnd=true);
/// inline implementations
inline void splitByLine(vector<string>& out, const string& in)
{
splitBy(out, in, "\n");
}
}
================================================
FILE: h/utils/stringDrawing.h
================================================
#pragma once
#include "stringUtils.h"
namespace str
{
// if max width is -1, it will autodetect
string getBoxedString(const string& in, string boxName="", bool showLineNums=false, bool alwaysWidthMax=false, int maxWidth=-1);
// it is assumed that the data is already padded
void putArrayInTreeNodeBox(vector<string>& data);
string putStringInTreeNodeBox(const string& in);
// note that the input may have newlines in each element
string makeList(vector<string>& data);
string makeRootUpBinaryTree(const string& root, const string& leftBranch, const string& rightBranch, const string& leftLeaf, const string& rightLeaf);
//string makeTreeSection(const string& root, vector<string>& leaves);
}
================================================
FILE: h/utils/stringNumConversion.h
================================================
#pragma once
#include "stringUtils.h"
namespace str
{
// returns an escape code that can be placed in a C++ string literal and will evaluate to the given char
string charToCppStringLiteralEscaped(unsigned char c);
// returns a base number with 0-9 being 0-9, 10-35 being a-z and 36-61 being A-Z
// if maxDigits is >=0 will return only the leftmost maxDigits
string intToBase62(unsigned int in, int maxDigits=-1);
// uses intToBase62 to convert ptrIn to a string that can be used in a C++ id
string ptrToUniqueStr(void* ptrIn, int digits=4);
}
================================================
FILE: h/utils/stringUtils.h
================================================
#pragma once
/// This string util header will slowly replace msclStringFuncs.h
#include <string>
using std::string;
#include <vector>
using std::vector;
namespace str
{
inline void nextGlyph(int& out, const string& in);
inline int getWidth(const string& in);
// returns the byte location of the given glyph
inline int seek(const string& in, int distGlyph, int startPosByte=0);
// currently is a straight equals, but in the future could do things such as evaluate strings with different types of newlines to equal
inline bool subMatches(const string& in, int posBytes, const string& sub);
// if endGlyph is -1 it takes till the end of the string
inline string sub(const string& in, int startGlyph, int endGlyph);
inline bool matches(const string& a, const string& b);
inline bool hasPrefix(const string& in, const string& prefix);
inline bool hasSuffix(const string& in, const string& suffix);
// returns the BYTE location (not glyph location), or -1 if pattern doesn't appear
//int searchFor(const string& in, string pattern, int startByte);
// returns the glyph position of the first occurrence of pattern, or -1 if it doesn't appear
int getGlyphPosOf(const string& in, string pattern);
string tabsToSpaces(const string& in, int tabWidth=4);
enum StringPadAlignment {ALIGNMENT_LEFT=1, ALIGNMENT_CENTER=0, ALIGNMENT_RIGHT=-1};
// alignment: 1 = left, -1 = right, 0 = center
// pad is assumed to be of width 1
string pad(const string& in, int size, StringPadAlignment alignment=ALIGNMENT_LEFT, string pad=" ", string leftCap="", string rightCap="");
/// inline implementations
inline void nextGlyph(int& out, const string& in)
{
do {
out++;
} while (out<(int)in.size() && (in[out] & 0x80) && !(in[out] & 0x40));
}
inline int getWidth(const string& in)
{
int glyphPos=0;
int bytePos=0;
while (bytePos<(int)in.size())
{
nextGlyph(bytePos, in);
glyphPos++;
}
return glyphPos;
}
inline int seek(const string& in, int distGlyph, int startPosByte)
{
int i=startPosByte;
while (distGlyph>0)
{
nextGlyph(i, in);
distGlyph--;
}
return i;
}
inline bool subMatches(const string& in, int posBytes, const string& sub)
{
if (posBytes<0 || sub.size()+posBytes>in.size())
return false;
for (int i=0; i<(int)sub.size(); i++)
{
if (in[i+posBytes]!=sub[i])
return false;
}
return true;
}
inline string sub(const string& in, int startGlyph, int endGlyph)
{
int startByte=seek(in, startGlyph);
int endByte=(endGlyph < 0 ? (int)in.size() : seek(in, endGlyph-startGlyph, startByte));
return in.substr(startByte, endByte-startByte);
}
inline bool matches(const string& a, const string& b)
{
if (a.size()!=b.size())
return false;
return subMatches(a, 0, b);
}
inline bool hasPrefix(const string& in, const string& prefix)
{
return subMatches(in, 0, prefix);
}
inline bool hasSuffix(const string& in, const string& suffix)
{
return subMatches(in, in.size()-suffix.size(), suffix);
}
}
#include "stringArray.h"
#include "stringDrawing.h"
================================================
FILE: other/pinecone.pn
================================================
print: argLen.String + " args:"
i: 0 | i < argLen | i: i + 1 @ (
print: arg: i
)
================================================
FILE: other/pinecone_concept.txt
================================================
# Programming language concept by Sophie Winter
# This is not ment to be actual code, just a place to exparament with different ideas of how the language might look
add={a=$ b=$ a+b}
a=7
b=3
z={sqrt(@)_}
add=z
add(&w &x w+x}, b)
b==3?
print("yes")
:b==4?
print("4")
:{
print(z)
add()
}
print(add(a))
max=
{
a,b,c=$
a>b && a>c? a
: b>c? b
: c
}
max=
{
a,b=$
a>b?a:b
}
max: a, b, c
print: "hello world, the numer is " 7
a>b?a,b
car.drive
"hello world".print
7,5.max
b:7
g:9.81
str:"hello world"
zero:Int
___________________________________________________
max$:
{
Int: z
>.z
}
$func:
{
a,b:$(Dub, Dub)
}
func:
{
a:tru
b:fls
a?
(
print: "hello"
9
),(
b? print: "world"
7)
}
func: (a: Int, b: Int):
{
a>b?
a+=3,
~b
i: 0, i<6, i++ @
(
b--
b<0?
~7
)
}
___________________________________________________
in: {Int, Int}
funcs: {Dub, Dub}, {Int, Bool}
out: error? #1?
in: {Int, Int}
funcs: {Dub, Int}, {Int, Dub}
out: error because tie
in: {Int, Int}
funcs: {Int, Bool}, {Dub, Bool}
out: #1
in: {Int, Dub}
funcs: {Int, Int}, {Dub, Dub}
out: #2
in: {Bool, Bool}
funcs: {Int, Int}, {Dub, Dub}
out: error because tie (only cares if more or less complex, not how much)
___________________________________________________
max: {a: Int, b: Int}:
~a>b?a|b
i: 0..8@
(
)
(i=0; i<b; ++i)
{
}
___________________________________________________
________
_ ______
_ _ ___
4+a: 5+3
|
/ \
/ / \
/ / /\
/ / / /\
4+a: 5+b: 3
___________________________________________________
a: 1 | a<100 | a++ @
(
)
func: {}|&Int.{}:
(
#do stuff
)
atan2: $Dub|{y: Dub, x: Dub}.
[
]
ang: (4, 5).atan2
atan2: {y: Dub; x: Dub}
[
]
___________________________________________________
a[b]
(a: (b))
i: 100
___________________________________________________
funcName:
{
^Int
a: Dub
b: Dub
}[
i: 10
(
j: 20
^j
)
(
j: 7
^j
)
]
doStuff: {me: String}
[
val: Int: me
val+: a
^val
]
___________________________________________________
a: 8
a: 12
b: a
c: {a: Int}
[
c=0 ?
~0
|
~c-1
]
a: 2 + c: 3+4
___________________________________________________
if a
(
# code
)
else
(
#[
this is a block comment
#]
)
___________________________________________________
a: tru
b: 9
while a=tru
(
b-:1
if b<0
a: fls
)
5-3-2
a: b: c
___________________________________________________
print: a # works because a is defined below
a:: 8 # constant
a: 7 # compile error
print: b # compile error
$b: 8 # variable
b: 7 # works
print: c # compile error
$c:: 8 # immutable
c: 7 # compile error
myFunc :: {val1: Int; val2: Int}
[
]
___________________________________________________
\+ :: {Int} < {a: Int}.{b: Int}
[
a+b^
]
func :: {me: Int | a: Dub} > {Int}
[
]
func :: {me: Int}.{a: Dub} > {Int}
[
]
___________________________________________________
\\
this
is
block
comment
//
//
this
is
block
comment
\\
\\ it looks great on one line too //
___________________________________________________
BaseClass ::
{
foo: Dub
}
MyObj ::
{
$super: BaseClass
a: Int
b: Int
}
MyObj :: {} > {MyObj}:
(
return: (9.3), 8, 12
)
addToBoth :: {$me: MyObj}.{}:
(
a+: 1
b+: 1
foo
)
myPrint: tru, 12, 8.9
obj: MyObj
obj.addToBoth
___________________________________________________
a: b: 7-1-1
:
/ \
a :
/ \
b -
/ \
- 1
/ \
7 1
___________________________________________________
a: {}
a.b: 8
a.c: "hello"
a . getString :: {}
[
c + " " + b
]
MyClass: {}
[
me.name: "Sophie"
me.age: 19
me
]
getString: {MyClass}.{}
[
name + " is " + age + " years old."
]
person: MyClass
print: person.getString
> Sophie is 19 years old
___________________________________________________
print "hello"
myFunc 8?
print "yes"
|
print "no"
myFunc {Int}
[
]
___________________________________________________
a.b.c: 8
:
/ \
. 8
/ \
. c
/ \
a b
___________________________________________________
i: 0 | i<100 | i: i+1 @
(
# do stuff
)
(i:0; i<100; i:i+1) @
(
# do stuff
)
___________________________________________________
myFunc :: {Int}.{Int} -> {Int}:
(
print: right
print: left
print
right>6 ?
left.myFunc: right-1
8
)
myFunc :: Int.Int: Int
(
print: right
print: left
print
right>6 ?
left.myFunc: right-1
8
)
___________________________________________________
myObj: MyObj: 9, 3
myPtr: &myObj
myObj = myPtr ? (
# valid
)
myObj2 = myPtr.me
___________________________________________________
myObj: MyObj.new: 9, 3
myPtr: myObj.ptr
myObj = myPtr ? (
# valid
)
myObj2 = myPtr.me
___________________________________________________
myFunc :: String.Int -> Dub
[
]
a: 9.7
b: int: a
___________________________________________________
var a
a(c: 9, d: 3)
___________________________________________________
a: c 9, d 3
___________________________________________________
a: happy: MyClass
b: MyClass
b: a.diff
___________________________________________________
================================================
FILE: other/readme.md
================================================
this directory is for miscellaneous files that don't really go anywhere else.
================================================
FILE: other/user_testing.txt
================================================
# what do you think the following code snippits mean?
# 1 _______________________________________________________________________
a>b?
~a,
~b
# 2 _______________________________________________________________________
a: (b: Dub, c: Dub).
(
# more code here
)
# 3 _______________________________________________________________________
a:
(
(b: Dub, c: Dub)=$
# more code here
)
# 4 _______________________________________________________________________
a:
{
b: Int
c: Dub
d: {Bool Bool}
}
# would you expect the following code to throw an error (assume no other code in the program)?
# if not, what would you expect it to output?
# 5 _______________________________________________________________________
i: 0, i<6, i++ @
print: i
# 6 _______________________________________________________________________
a: 3
b: 2.8
print: a+b
# 7 _______________________________________________________________________
a: 3
b: 2.8
print: a+(Int: b)
# 8 _______________________________________________________________________
a: Int
print: a
a+=1
print: a
# 9
# do you prefer ++a, or a++ to increment a variable?
a: 5
print: a++
================================================
FILE: readme.md
================================================
# The Pinecone Programming Language
**_Built from the ground up to be fast, concise and intuitive._**
## NOTE: PINECONE IS NO LONGER BEING ACTIVELY DEVELOPED OR MAINTAINED ##
Pinecone 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.
__If you want to program in Pinecone now, see the [tutorials](tutorials/index.md) for how to get started.__
__There is also a Pinecone plugin for VIM [here](https://github.com/wsKilljoy/vim-pinecone).__
__For updates, discussion and help, take a look at the Pinecone subreddit: [/r/PineconeLang](https://www.reddit.com/r/PineconeLang/)__
## About
Pinecone 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.).
## Example
Here 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).
```
# FizzBuzz
# call the function defined below
fizzBuzz: 1, 20
# define the FizzBuzz function
fizzBuzz :: {start: Int, end: Int}: (
# loop i from start to end
i: in.start | i <= in.end | i: i+1 @ (
# use conditionals to print the right thing
i % 3 = 0 && i % 5 = 0 ?
print: "FizzBuzz"
|
i % 3 = 0 ?
print: "Fizz"
|
i % 5 = 0 ?
print: "Buzz"
|
print: i
)
)
```
## Why?
This 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.
Pinecone 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:
* Variable creation is implicit, just set a variable and it is created.
* Variables are statically typed, but type deduction is automatic.
* Calling a function that takes no arguments is the same syntax as accessing a variable (just writing it's name).
* Calling a function that takes one argument is the same syntax as setting or creating a variable (`funcOrVar: input`).
* Calling a function that takes multiple arguments is the same syntax as setting or creating a tuple (`funcOrTuple: input1, input2`).
* White space is ignored _and_ semicolons are not necessary
* `:` is used for assignment, which leaves `=` free for comparison, rather than the often confusing `==`.
* Tuples, structs and classes are all basically the same thing
* 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).
* Program control is done with operators instead of keywords (`?` instead of `if`)
## Compatibility
Pinecone 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.
## Current State
The features that are currently implemented are as follows:
* Primitive data types `Bool`, `Int` and `Dub`
* All the operators you would expect (`+`, `*`, `%`, `:`, `=`, `>`, `<=`, `&&`, etc.)
* Single and multi line comments
* Flow control (if, if/else, while loop, for loop)
* Constants
* Data structs
* Tuples
* Int arrays
* Functions
* Strings and various String operations
* User input
* Running system commands
* Interpreter for rapid development and simplicity
* Transpiler to C++ for max performance
The following features are coming soon:
* Whatev type (equivalent to templates or generics in other languages)
* Arrays of any type (Whatev support needed)
* Pass-by-reference
* Proper classes (pass-by-reference needed)
* Operator overloading
## Contributing
I 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.
================================================
FILE: repl/readme.md
================================================
## Repl
`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.
To run the repl (after pinecone has been installed):
* Make the `repl.sh` excitable: `chmod +x repl/repl.sh`
* Run with `./repl/repl.sh`
* Optional: Create an alias. Add `alias pinecone=".../path/to/pinecone/repl/repl.sh"` to your `.rc` file (`~/.bashrc`, `~/.zshrc`, ect.).
Commands:
* `.clear`: Clears the repl.
* `.read` : Prints what is in the repl.
* `.exit` : Exits the repl (same as ^C).
================================================
FILE: repl/repl.sh
================================================
#!/bin/bash
echo "" > ./repl/tmp.pn;
while [ true ]
do
read -p "> " cmd;
if [ "$cmd" == ".clear" ]; then
echo "" > ./repl/tmp.pn;
clear;
echo "[cleared]";
elif [ "$cmd" == ".exit" ]; then
exit 0;
elif [ "$cmd" == ".read" ]; then
cat ./repl/tmp.pn;
else
echo $cmd >> ./repl/tmp.pn;
echo " -- ";
./pinecone ./repl/tmp.pn;
fi
done
================================================
FILE: src/Actions/Action.cpp
================================================
#include "../../h/Action.h"
#include "../../h/ErrorHandler.h"
#include "../../h/msclStringFuncs.h"
ActionData::ActionData(Type returnTypeIn, Type inLeftTypeIn, Type inRightTypeIn)
{
returnType=returnTypeIn;
inLeftType=inLeftTypeIn;
inRightType=inRightTypeIn;
if (!returnType || !inLeftType || !inRightType)
{
throw PineconeError("ActionData created with null type", INTERNAL_ERROR);
}
}
string ActionData::toString()
{
return description;
//return returnType->getName() + " <- " + inLeftType->getName() + " " + text + " " + inRightType->getName();
}
string ActionData::getTypesString()
{
return returnType->getString()+" <- "+inLeftType->getString()+"."+inRightType->getString();
}
//LambdaAction::LambdaAction(Type returnTypeIn, function<void*(void*,void*)> lambdaIn, Type inLeftTypeIn, Type inRightTypeIn, string textIn)
//void* LambdaAction::execute(void* inLeft, void* inRight)
class VoidAction: public ActionData
{
public:
VoidAction(): ActionData(Void, Void, Void)
{
setDescription("Void Action");
}
void* execute(void* inLeft, void* inRight)
{
return nullptr;
}
void addToProg(Action inLeft, Action inRight, CppProgram* prog)
{
if (prog->getExprLevel()>0)
prog->comment("void");
}
string getDescription()
{
return str::putStringInTreeNodeBox("void");
}
};
class LambdaAction: public ActionData
{
public:
LambdaAction(Type inLeftTypeIn, Type inRightTypeIn, Type returnTypeIn,
function<void*(void*,void*)> lambdaIn,
function<void(Action inLeft, Action inRight, CppProgram* prog)> cppWriterIn,
string textIn)
: ActionData(returnTypeIn, inLeftTypeIn, inRightTypeIn)
{
if (cppWriterIn==nullptr)
{
cppWriter=[=](Action inLeft, Action inRight, CppProgram* prog)
{
prog->comment("lambda action '"+textIn+"' has not yet been implemented for C++");
};
}
else
{
cppWriter=cppWriterIn;
}
if (lambdaIn==nullptr)
{
lambdaIn=[=](void* inLeft, void* inRight)->void*
{
throw PineconeError("action '"+textIn+"' has not yet been implemented for the interpreter", RUNTIME_ERROR);
};
}
else
{
lambda=lambdaIn;
}
setDescription(textIn);
}
void* execute(void* inLeft, void* inRight)
{
return lambda(inLeft, inRight);
}
void addToProg(Action inLeft, Action inRight, CppProgram* prog)
{
cppWriter(inLeft, inRight, prog);
}
string getDescription()
{
return str::putStringInTreeNodeBox(description);
}
private:
function<void*(void*,void*)> lambda;
function<void(Action inLeft, Action inRight, CppProgram* prog)> cppWriter;
string cppCode;
};
Action lambdaAction(Type inLeftTypeIn, Type inRightTypeIn, Type returnTypeIn,
function<void*(void*,void*)> lambdaIn,
function<void(Action inLeft, Action inRight, CppProgram* prog)> cppWriter,
string textIn)
{
return Action(new LambdaAction(inLeftTypeIn, inRightTypeIn, returnTypeIn, lambdaIn, cppWriter, textIn));
}
Action createNewVoidAction()
{
return Action(new VoidAction());
}
================================================
FILE: src/Actions/BoolOpAction.cpp
================================================
#include "../../h/Action.h"
#include "../../h/ErrorHandler.h"
#include "../../h/utils/stringDrawing.h"
class AndAction: public ActionData
{
public:
AndAction(Action firstActionIn, Action secondActionIn)
:ActionData(Bool, Void, Void)
{
firstAction=firstActionIn;
secondAction=secondActionIn;
if (firstAction->getReturnType()!=Bool)
{
throw PineconeError("AndAction created with first action that does not return Bool", INTERNAL_ERROR);
}
if (secondAction->getReturnType()!=Bool)
{
throw PineconeError("AndAction created with second action that does not return Bool", INTERNAL_ERROR);
}
}
string getDescription()
{
return str::makeRootUpBinaryTree("&&", firstAction->getReturnType()->getName(), secondAction->getReturnType()->getName(), firstAction->getDescription(), secondAction->getDescription());
//return firstAction->getDescription() + " && " + firstAction->getDescription();
}
void* execute(void* inLeft, void* inRight)
{
bool* out=(bool*)malloc(sizeof(bool));
*out=false;
void* firstVal=firstAction->execute(nullptr, nullptr);
if (*((bool*)firstVal))
{
void* secondVal=secondAction->execute(nullptr, nullptr);
if (*((bool*)secondVal))
{
*out=true;
}
free(secondVal);
}
free(firstVal);
return out;
}
void addToProg(Action inLeft, Action inRight, CppProgram* prog)
{
prog->pushExpr();
firstAction->addToProg(voidAction, voidAction, prog);
prog->popExpr();
prog->code(" && ");
prog->pushExpr();
secondAction->addToProg(voidAction, voidAction, prog);
prog->popExpr();
}
private:
Action firstAction;
Action secondAction;
};
class OrAction: public ActionData
{
public:
OrAction(Action firstActionIn, Action secondActionIn)
:ActionData(Bool, Void, Void)
{
firstAction=firstActionIn;
secondAction=secondActionIn;
if (firstAction->getReturnType()!=Bool)
{
throw PineconeError("OrAction created with first action that does not return Bool", INTERNAL_ERROR);
}
if (secondAction->getReturnType()!=Bool)
{
throw PineconeError("OrAction created with second action that does not return Bool", INTERNAL_ERROR);
}
}
string getDescription()
{
return str::makeRootUpBinaryTree("||", firstAction->getReturnType()->getName(), secondAction->getReturnType()->getName(), firstAction->getDescription(), secondAction->getDescription());
}
void* execute(void* inLeft, void* inRight)
{
bool* out=(bool*)malloc(sizeof(bool));
*out=true;
void* firstVal=firstAction->execute(nullptr, nullptr);
if (!*((bool*)firstVal))
{
void* secondVal=secondAction->execute(nullptr, nullptr);
if (!*((bool*)secondVal))
{
*out=false;
}
free(secondVal);
}
free(firstVal);
return out;
}
void addToProg(Action inLeft, Action inRight, CppProgram* prog)
{
prog->pushExpr();
firstAction->addToProg(voidAction, voidAction, prog);
prog->popExpr();
prog->code(" || ");
prog->pushExpr();
secondAction->addToProg(voidAction, voidAction, prog);
prog->popExpr();
}
private:
Action firstAction;
Action secondAction;
};
Action andAction(Action firstActionIn, Action secondActionIn)
{
return Action(new AndAction(firstActionIn, secondActionIn));
}
Action orAction(Action firstActionIn, Action secondActionIn)
{
return Action(new OrAction(firstActionIn, secondActionIn));
}
================================================
FILE: src/Actions/BranchAction.cpp
================================================
#include "../../h/Action.h"
#include "../../h/ErrorHandler.h"
#include "../../h/CppProgram.h"
#include "../../h/utils/stringDrawing.h"
class BranchAction: public ActionData
{
public:
BranchAction(Action leftInputIn, Action actionIn, Action rightInputIn)
:ActionData(actionIn->getReturnType(), Void, Void)
{
if (!actionIn)
throw PineconeError(string() + "branch action created sent null action", INTERNAL_ERROR);
if (!leftInputIn)
throw PineconeError(string() + "branch action created sent null leftInput", INTERNAL_ERROR);
if (!rightInputIn)
throw PineconeError(string() + "branch action created sent null rightInput", INTERNAL_ERROR);
action=actionIn;
leftInput=leftInputIn;
rightInput=rightInputIn;
if (!leftInput->getInLeftType()->matches(Void) || !leftInput->getInRightType()->matches(Void))
{
throw PineconeError(leftInput->getDescription() + " put into branch even though its inputs are not void", INTERNAL_ERROR);
}
if (!rightInput->getInLeftType()->matches(Void) || !rightInput->getInRightType()->matches(Void))
{
throw PineconeError(rightInput->getDescription() + " put into branch even though its inputs are not void", INTERNAL_ERROR);
}
if (!leftInput->getReturnType()->matches(action->getInLeftType()))
{
throw PineconeError(leftInput->getDescription() + " return type is not the same as the left input of " + action->getDescription(), INTERNAL_ERROR);
}
if (!rightInput->getReturnType()->matches(action->getInRightType()))
{
throw PineconeError(rightInput->getDescription() + " return type is not the same as the right input of " + action->getDescription(), INTERNAL_ERROR);
}
}
string getDescription()
{
if (leftInput && action && rightInput)
{
return str::makeRootUpBinaryTree(action->getDescription(), leftInput->getReturnType()->getName(), rightInput->getReturnType()->getName(), leftInput->getDescription(), rightInput->getDescription());
//return getReturnType()->toString() + " <- [" + leftInput->getDescription() + "].[" + action->getDescription() + "]:[" + rightInput->getDescription() + "]";
//return "(" + leftInput->getDescription() + " -> " + action->getDescription() + " <- " + rightInput->getDescription() + ")";
//return getReturnType()->getName() + " <- " + leftInput->getDescription() + "." + action->getDescription() + ":" + rightInput->getDescription();
}
else
return "[branch with null element]";
}
void* execute(void* inLeft, void* inRight)
{
void* leftData=leftInput->execute(nullptr, nullptr);
void* rightData=rightInput->execute(nullptr, nullptr);
void* outData=action->execute(leftData, rightData);
free(leftData);
free(rightData);
return outData;
}
void addToProg(Action inLeft, Action inRight, CppProgram* prog)
{
Action leftInTmp = leftInput;
Action rightInTmp = rightInput;
if (leftInTmp->getReturnType()!=action->getInLeftType())
leftInTmp=cppTupleCastAction(leftInTmp, action->getInLeftType());
if (rightInTmp->getReturnType()!=action->getInRightType())
rightInTmp=cppTupleCastAction(rightInTmp, action->getInRightType());
action->addToProg(leftInTmp, rightInTmp, prog);
}
private:
Action action;
Action leftInput;
Action rightInput;
};
class RightBranchAction: public ActionData
{
public:
RightBranchAction(Action actionIn, Action rightInputIn)
:ActionData(actionIn->getReturnType(), Void, Void)
{
if (!actionIn)
throw PineconeError(string() + "branch action created sent null action", INTERNAL_ERROR);
if (!rightInputIn)
throw PineconeError(string() + "branch action created sent null rightInput", INTERNAL_ERROR);
action=actionIn;
rightInput=rightInputIn;
if (!rightInput->getInLeftType()->matches(Void) || !rightInput->getInRightType()->matches(Void))
{
throw PineconeError(rightInput->getDescription() + " put into branch even though its inputs are not void", INTERNAL_ERROR);
}
if (!rightInput->getReturnType()->matches(action->getInRightType()))
{
throw PineconeError(rightInput->getDescription() + " return type is not the same as the right input of " + action->getDescription(), INTERNAL_ERROR);
}
}
~RightBranchAction()
{
}
string getDescription()
{
if (action && rightInput)
{
return str::makeRootUpBinaryTree(action->getDescription(), "", rightInput->getReturnType()->getName(), "", rightInput->getDescription());
//return getReturnType()->toString() + " <- [" + leftInput->getDescription() + "].[" + action->getDescription() + "]:[" + rightInput->getDescription() + "]";
//return "(" + action->getDescription() + " <- " + rightInput->getDescription() + ")";
//return getReturnType()->getName() + " <- " + leftInput->getDescription() + "." + action->getDescription() + ":" + rightInput->getDescription();
}
else
return "[branch with null element]";
}
void* execute(void* inLeft, void* inRight)
{
void* rightData=rightInput->execute(nullptr, nullptr);
void* outData=action->execute(nullptr, rightData);
free(rightData);
return outData;
}
void addToProg(Action inLeft, Action inRight, CppProgram* prog)
{
Action rightInTmp = rightInput;
if (rightInTmp->getReturnType()!=action->getInRightType())
rightInTmp=cppTupleCastAction(rightInTmp, action->getInRightType());
action->addToProg(voidAction, rightInTmp, prog);
}
private:
Action action=nullptr;
Action rightInput=nullptr;
};
class LeftBranchAction: public ActionData
{
public:
LeftBranchAction(Action leftInputIn, Action actionIn)
:ActionData(actionIn->getReturnType(), Void, Void)
{
if (!actionIn)
throw PineconeError(string() + "branch action created sent null action", INTERNAL_ERROR);
if (!leftInputIn)
throw PineconeError(string() + "branch action created sent null leftInput", INTERNAL_ERROR);
action=actionIn;
leftInput=leftInputIn;
if (!leftInput->getInLeftType()->matches(Void) || !leftInput->getInRightType()->matches(Void))
{
throw PineconeError(leftInput->getDescription() + " put into branch even though its inputs are not void", INTERNAL_ERROR);
}
if (!leftInput->getReturnType()->matches(action->getInLeftType()))
{
throw PineconeError(leftInput->getDescription() + " return type is not the same as the left input of " + action->getDescription(), INTERNAL_ERROR);
}
}
string getDescription()
{
if (leftInput && action)
{
return str::makeRootUpBinaryTree(action->getDescription(), leftInput->getReturnType()->getName(), "", leftInput->getDescription(), "");
//return getReturnType()->toString() + " <- [" + leftInput->getDescription() + "].[" + action->getDescription() + "]:[" + rightInput->getDescription() + "]";
//return "(" + leftInput->getDescription() + " -> " + action->getDescription() + ")";
//return getReturnType()->getName() + " <- " + leftInput->getDescription() + "." + action->getDescription() + ":" + rightInput->getDescription();
}
else
return "[branch with null element]";
}
void* execute(void* inLeft, void* inRight)
{
void* leftData=leftInput->execute(nullptr, nullptr);
void* outData=action->execute(leftData, nullptr);
free(leftData);
return outData;
}
void addToProg(Action inLeft, Action inRight, CppProgram* prog)
{
Action leftInTmp = leftInput;
if (leftInTmp->getReturnType()!=action->getInLeftType())
leftInTmp=cppTupleCastAction(leftInTmp, action->getInLeftType());
action->addToProg(leftInTmp, voidAction, prog);
}
private:
Action leftInput;
Action action;
};
Action branchAction(Action leftInputIn, Action actionIn, Action rightInputIn)
{
//return Action(new BranchAction(leftInputIn, actionIn, rightInputIn));
if (leftInputIn->getReturnType()->isVoid())
{
if (rightInputIn->getReturnType()->isVoid())
{
return actionIn;
}
else
{
return Action(new RightBranchAction(actionIn, rightInputIn));
}
}
else
{
if (rightInputIn->getReturnType()->isVoid())
{
return Action(new LeftBranchAction(leftInputIn, actionIn));
}
else
{
return Action(new BranchAction(leftInputIn, actionIn, rightInputIn));
}
}
}
================================================
FILE: src/Actions/FunctionAction.cpp
================================================
#include "../../h/Action.h"
#include "../../h/ErrorHandler.h"
#include "../../h/StackFrame.h"
#include "../../h/AstNode.h"
#include "../../h/utils/stringNumConversion.h"
#include "../../h/utils/stringUtils.h"
#include <cstring> //for memcpy
using std::memcpy;
class FunctionAction: public ActionData
{
public:
FunctionAction(Action actionIn, shared_ptr<StackFrame> stackFameIn):
ActionData(actionIn->getReturnType(), stackFameIn->getLeftInType(), stackFameIn->getRightInType())
{
stackFame=stackFameIn;
action=actionIn;
node=nullptr;
setDescription("function ("+getInLeftType()->getString()+"."+getInRightType()->getString()+" > "+getReturnType()->getString()+")");
if (action->getInLeftType()!=Void || action->getInRightType()!=Void)
{
throw PineconeError(action->getDescription() + " put into function even though its inputs are not void", INTERNAL_ERROR);
}
}
FunctionAction(AstNode nodeIn, Type returnTypeIn, shared_ptr<StackFrame> stackFameIn):
ActionData(returnTypeIn, stackFameIn->getLeftInType(), stackFameIn->getRightInType())
{
stackFame=stackFameIn;
node=move(nodeIn);
action=nullptr;
setDescription("function ("+getInLeftType()->getString()+"."+getInRightType()->getString()+" > "+getReturnType()->getString()+")");
}
void resolveAction()
{
if (!node || action)
{
throw PineconeError("FunctionAction::resolveAction called when this action is in the wrong state", INTERNAL_ERROR);
}
action=node->getAction();
if (!returnType->isVoid() && !returnType->matches(action->getReturnType()))
{
// the objects that are being returned are being destroyed before the function exits
// also another problem: if a function returns a thing but nothing accepts the output, the destructor is not called
//throw PineconeError("function body returns "+action->getReturnType()->getString()+" instead of "+returnType->getString(), SOURCE_ERROR, node->getToken());
throw PineconeError("function body returns "+action->getReturnType()->getString()+" instead of "+returnType->getString()+"\n"+action->getDescription(), SOURCE_ERROR, node->getToken());
}
if (!action->getInLeftType()->isVoid() || !action->getInRightType()->isVoid())
{
throw PineconeError(action->getDescription() + " put into function even though its inputs are not void", INTERNAL_ERROR);
}
}
string getDescription()
{
return str::putStringInTreeNodeBox("call func "+nameHint);
//if (!action)
// resolveAction();
//return "func: " + description;//action->getDescription();
}
bool isFunction() {return true;}
void* execute(void* inLeft, void* inRight)
{
if (!action)
resolveAction();
void * oldStackPtr=stackPtr;
stackPtr=malloc(stackFame->getSize());
if (inLeft)
memcpy((char*)stackPtr+stackFame->getLeftOffset(), inLeft, getInLeftType()->getSize());
if (inRight)
memcpy((char*)stackPtr+stackFame->getRightOffset(), inRight, getInRightType()->getSize());
void* out=action->execute(nullptr, nullptr);
free(stackPtr);
stackPtr=oldStackPtr;
return out;
}
void addToProg(Action inLeft, Action inRight, CppProgram* prog)
{
if (!action)
{
resolveAction();
}
// construct a unique name that will NEVER collide with another funtion (even in the case of overloaded functions with the same Pinecone name)
// 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
string name="%";
name+=(nameHint.empty() ? "func" : nameHint);
name+="_"+str::ptrToUniqueStr(&*action);
//name+="_"+getInLeftType()->getCompactString()+"_"+getInRightType()->getCompactString();
/*
if (str::hasSuffix(nameHint, "_CPP"))
name=nameHint.substr(0, nameHint.size()-4);
*/
if (!prog->hasFunc(name))
{
prog->pushFunc(name, getInLeftType(), getInRightType(), getReturnType());
if (getReturnType()->isCreatable() && action->getReturnType()!=getReturnType())
{
cppTupleCastAction(action, getReturnType())->addToProg(prog);
}
else
{
action->addToProg(prog);
}
prog->endln();
prog->popFunc();
}
prog->name(name);
prog->pushExpr();
/*
bool hasStarted=false;
if (getInLeftType()->getType()==TypeBase::TUPLE)
{
for (auto i: *getInLeftType()->getAllSubTypes())
{
if (hasStarted)
prog->code(", ");
hasStarted=true;
getElemFromTupleAction(getInLeftType(), i.name)->addToProg(inLeft, voidAction, prog);
}
}
else if (!getInLeftType()->isCreatable())
{
// do nothing
}
else
{
if (hasStarted)
prog->code(", ");
hasStarted=true;
inLeft->addToProg(prog);
}
if (getInRightType()->getType()==TypeBase::TUPLE)
{
for (auto i: *getInRightType()->getAllSubTypes())
{
if (hasStarted)
prog->code(", ");
hasStarted=true;
getElemFromTupleAction(getInRightType(), i.name)->addToProg(inRight, voidAction, prog);
}
}
else if (!getInRightType()->isCreatable())
{
// do nothing
}
else
{
if (hasStarted)
prog->code(", ");
hasStarted=true;
inRight->addToProg(prog);
}
//prog->code(", ");
//inRight->addToProg(prog);
*/
if (getInLeftType()->isCreatable())
{
inLeft->addToProg(prog);
}
if (getInRightType()->isCreatable())
{
if (getInLeftType()->isCreatable())
prog->code(", ");
inRight->addToProg(prog);
}
prog->popExpr();
//prog->comment("function transpiling not yet implemented");
}
private:
shared_ptr<StackFrame> stackFame;
Action action=nullptr;
AstNode node=nullptr;
};
Action functionAction(Action actionIn, shared_ptr<StackFrame> stackFameIn)
{
return Action(new FunctionAction(actionIn, stackFameIn));
}
Action functionAction(AstNode nodeIn, Type returnTypeIn, shared_ptr<StackFrame> stackFameIn)
{
return Action(new FunctionAction(move(nodeIn), returnTypeIn, stackFameIn));
}
================================================
FILE: src/Actions/IfAction.cpp
================================================
#include "../../h/Action.h"
#include "../../h/ErrorHandler.h"
class IfAction: public ActionData
{
public:
IfAction(Action conditionIn, Action ifActionIn)
:ActionData(Void, Void, Void)
{
condition=conditionIn;
ifAction=ifActionIn;
if (condition->getReturnType()!=Bool)
{
error.log("IfAction created with condition action that does not return Bool", INTERNAL_ERROR);
}
if (condition->getInLeftType()!=Void || condition->getInRightType()!=Void)
{
error.log("IfAction created with condition action that takes in something other then Void", INTERNAL_ERROR);
}
if (ifAction->getInLeftType()!=Void || ifAction->getInRightType()!=Void)
{
error.log("IfAction created with action that takes in something other then Void", INTERNAL_ERROR);
}
}
string getDescription()
{
return str::makeRootUpBinaryTree("?", condition->getReturnType()->getName(), "", condition->getDescription(), ifAction->getDescription());
//return "if " + condition->getDescription() + " then " + ifAction->getDescription();
}
void* execute(void* inLeft, void* inRight)
{
void* conditionOut=condition->execute(nullptr, nullptr);
if (*((bool*)conditionOut))
{
free(ifAction->execute(nullptr, nullptr));
}
free(conditionOut);
return nullptr;
}
void addToProg(Action inLeft, Action inRight, CppProgram* prog)
{
prog->code("if ");
prog->pushExpr();
condition->addToProg(voidAction, voidAction, prog);
prog->popExpr();
prog->pushBlock();
ifAction->addToProg(voidAction, voidAction, prog);
prog->endln();
prog->popBlock();
}
private:
Action condition;
Action ifAction;
};
class IfElseAction: public ActionData
{
public:
IfElseAction(Action conditionIn, Action ifActionIn, Action elseActionIn)
:ActionData([&](){return ifActionIn->getReturnType()->matches(elseActionIn->getReturnType())?ifActionIn->getReturnType():Void;}(), Void, Void)
{
returnVal=getReturnType()!=Void;
condition=conditionIn;
ifAction=ifActionIn;
elseAction=elseActionIn;
if (condition->getReturnType()!=Bool)
{
error.log("IfElseAction created with condition action that does not return Bool", INTERNAL_ERROR);
}
if (condition->getInLeftType()!=Void || condition->getInRightType()!=Void)
{
error.log("IfElseAction created with conditiofn action that takes in something other then Void", INTERNAL_ERROR);
}
if (ifAction->getInLeftType()!=Void || ifAction->getInRightType()!=Void)
{
error.log("IfElseAction created with action that takes in something other then Void", INTERNAL_ERROR);
}
}
string getDescription()
{
string branch=str::makeRootUpBinaryTree("╭┴╮\n│ │", "fls", "tru", elseAction->getDescription(), ifAction->getDescription());
return str::makeRootUpBinaryTree("?", condition->getReturnType()->getName(), "", condition->getDescription(), branch);
//return "if " + condition->getDescription() + " then " + ifAction->getDescription();
}
/*
string getCSource(string inLeft, string inRight)
{
return "if (" + condition->getCSource() + ")\n{\n" + ifAction->getCSource() + "\n} else {\n" + elseAction->getCSource() + "\n}";
}
*/
void* execute(void* inLeft, void* inRight)
{
void* out;
void* conditionOut=condition->execute(nullptr, nullptr);
if (*((bool*)conditionOut))
{
out=ifAction->execute(nullptr, nullptr);
}
else
{
out=elseAction->execute(nullptr, nullptr);
}
free(conditionOut);
if (returnVal)
{
return out;
}
else
{
free(out);
return nullptr;
}
}
void addToProg(Action inLeft, Action inRight, CppProgram* prog)
{
if (returnVal && prog->getExprLevel()>0)
{
prog->pushExpr();
condition->addToProg(voidAction, voidAction, prog);
prog->popExpr();
prog->code(" ? ");
prog->pushExpr();
ifAction->addToProg(voidAction, voidAction, prog);
prog->popExpr();
prog->code(" : ");
prog->pushExpr();
elseAction->addToProg(voidAction, voidAction, prog);
prog->popExpr();
}
else
{
prog->code("if ");
prog->pushExpr();
condition->addToProg(voidAction, voidAction, prog);
prog->popExpr();
prog->pushBlock();
ifAction->addToProg(voidAction, voidAction, prog);
prog->endln();
prog->popBlock();
prog->code("else");
prog->pushBlock();
elseAction->addToProg(voidAction, voidAction, prog);
prog->endln();
prog->popBlock();
}
}
private:
Action condition;
Action ifAction;
Action elseAction;
bool returnVal=false;
};
Action ifAction(Action conditionIn, Action ifActionIn)
{
return Action(new IfAction(conditionIn, ifActionIn));
}
Action ifElseAction(Action conditionIn, Action ifActionIn, Action elseAction)
{
return Action(new IfElseAction(conditionIn, ifActionIn, elseAction));
}
================================================
FILE: src/Actions/ListAction.cpp
================================================
#include "../../h/Action.h"
#include "../../h/ErrorHandler.h"
class ListAction: public ActionData
{
public:
ListAction(const vector<Action>& actionsIn, const vector<Action>& destroyersIn):
ActionData
(
(actionsIn.size()>0?actionsIn.back()->getReturnType():Void),
Void, Void
)
{
actions=actionsIn;
destroyers=destroyersIn;
for (auto i=actions.begin(); i!=actions.end(); ++i)
{
if (!(*i)->getInLeftType()->matches(Void) || !(*i)->getInRightType()->matches(Void))
{
error.log((*i)->getDescription() + " put into action list even though its inputs are not void", INTERNAL_ERROR);
}
}
}
~ListAction()
{
}
string getDescription()
{
vector<string> data;
for (auto i=actions.begin(); i!=actions.end(); ++i)
{
if (*i)
data.push_back((*i)->getDescription());
else
data.push_back(str::putStringInTreeNodeBox("[null action]"));
}
return str::makeList(data);
/*
string out;
out+="\n{";
for (auto i=actions.begin(); i!=actions.end(); ++i)
{
out+="\n\t";
string str;
if (*i)
str=(*i)->getDescription();
else
str="[null action]";
for (unsigned j=0; j<str.size(); ++j)
{
out+=str[j];
if (str[j]=='\n')
out+='\t';
}
out+="\n";
}
out+="}\n";
return out;
*/
}
void* execute(void* inLeft, void* inRight)
{
auto i=actions.begin();
for (; i!=std::prev(actions.end()); ++i)
{
free((*i)->execute(nullptr, nullptr));
}
void* returnVal=(*i)->execute(nullptr, nullptr);
for (auto j: destroyers)
{
free(j->execute(nullptr, nullptr));
}
return returnVal;
}
void addToProg(Action inLeft, Action inRight, CppProgram* prog)
{
addToProg(prog, getReturnType());
}
void addToProg(CppProgram* prog, Type returnType)
{
bool shouldReturn=(prog->getBlockLevel()==0 && prog->getIfReturnsVal()) && !prog->isMain();
prog->pushBlock();
for (auto i: actions)
{
if (shouldReturn && i==actions.back())
{
prog->declareVar("-out", returnType);
prog->name("-out");
prog->code(" = ");
if (i->getReturnType()!=returnType)
{
cppTupleCastAction(i, returnType)->addToProg(prog);
}
else
{
i->addToProg(prog);
}
}
else
{
i->addToProg(prog);
}
prog->endln();
}
for (auto i: destroyers)
{
i->addToProg(prog);
prog->endln();
}
if (shouldReturn)
{
prog->code("return ");
prog->name("-out");
prog->endln();
}
prog->popBlock();
}
/*
string getCSource(string inLeft, string inRight)
{
string out;
for (auto i: actions)
{
out+=i->getCSource()+";\n";
}
return out;
}
*/
private:
vector<Action> actions;
vector<Action> destroyers;
};
void addListToProgWithCppCasting(ListAction* list, Type returnType, CppProgram* prog)
{
list->addToProg(prog, returnType);
}
Action listAction(const vector<Action>& actionsIn, const vector<Action>& destroyersIn)
{
if (actionsIn.size()==0 && destroyersIn.size()==0)
{
return voidAction;
}
else if (actionsIn.size()==1 && destroyersIn.size()==0)
{
return actionsIn[0];
}
else
{
return Action(new ListAction(actionsIn, destroyersIn));
}
}
================================================
FILE: src/Actions/LoopAction.cpp
================================================
#include "../../h/Action.h"
#include "../../h/ErrorHandler.h"
class LoopAction: public ActionData
{
public:
LoopAction(Action conditionIn, Action endActionIn, Action loopActionIn)
:ActionData(Void, Void, Void)
{
condition=conditionIn;
loopAction=loopActionIn;
endAction=endActionIn;
if (condition->getReturnType()!=Bool)
{
error.log("LoopAction created with condition action that does not return Bool", INTERNAL_ERROR);
}
if (condition->getInLeftType()!=Void || condition->getInRightType()!=Void)
{
error.log("LoopAction created with condition action that takes in something other then Void", INTERNAL_ERROR);
}
if (loopAction->getInLeftType()!=Void || loopAction->getInRightType()!=Void)
{
error.log("LoopAction created with action that takes in something other then Void", INTERNAL_ERROR);
}
}
string getDescription()
{
string body=loopAction->getDescription();
if (endAction!=voidAction)
{
vector<string> data={body, endAction->getDescription()};
body=str::makeList(data);
}
return str::makeRootUpBinaryTree("@", condition->getReturnType()->getName(), "", condition->getDescription(), body);
//return "while " + condition->getDescription() + " do " + loopAction->getDescription();
}
void* execute(void* inLeft, void* inRight)
{
void* conditionOut;
while (true)
{
conditionOut=condition->execute(nullptr, nullptr);
if (!(*((bool*)conditionOut)))
break;
free(conditionOut);
free(loopAction->execute(nullptr, nullptr));
free(endAction->execute(nullptr, nullptr));
}
free(conditionOut);
return nullptr;
}
/*
string getCSource(string inLeft, string inRight)
{
string out;
out+="while (";
out+=condition->getCSource();
out+=")\n{";
out+=loopAction->getCSource();
out+=endAction->getCSource();
out+="\n}";
return out;
}
*/
void addToProg(Action inLeft, Action inRight, CppProgram* prog)
{
prog->code("while ");
prog->pushExpr();
condition->addToProg(prog);
prog->popExpr();
prog->pushBlock();
loopAction->addToProg(prog);
prog->endln();
if (endAction!=voidAction)
{
endAction->addToProg(prog);
prog->endln();
}
prog->popBlock();
}
private:
Action condition;
Action loopAction;
Action endAction;
};
Action loopAction(Action conditionIn, Action loopActionIn)
{
return Action(new LoopAction(conditionIn, voidAction, loopActionIn));
}
Action loopAction(Action conditionIn, Action endActionIn, Action loopActionIn)
{
return Action(new LoopAction(conditionIn, endActionIn, loopActionIn));
}
================================================
FILE: src/Actions/MakeTupleAction.cpp
================================================
#include "../../h/Action.h"
#include "../../h/ErrorHandler.h"
#include <vector>
#include <typeinfo>
using std::vector;
class GetElemFromTupleAction;
class CppTupleCastAction;
class ListAction;
void addListToProgWithCppCasting(ListAction* list, Type returnType, CppProgram* prog);
class MakeTupleAction: public ActionData
{
public:
MakeTupleAction(const vector<Action>& sourceActionsIn):
ActionData(
[&]() -> Type
{
TupleTypeMaker tuple;
for (auto i=sourceActionsIn.begin(); i!=sourceActionsIn.end(); ++i)
{
tuple.add((*i)->getReturnType());
}
return tuple.get(true);
}(),
Void, Void
)
{
if (sourceActionsIn.size()<=0)
{
error.log("MakeTupleAction created with empty list", INTERNAL_ERROR);
}
sourceActions=sourceActionsIn;
for (auto i=sourceActions.begin(); i!=sourceActions.end(); ++i)
{
if (!(*i)->getInLeftType()->matches(Void) || !(*i)->getInRightType()->matches(Void))
{
error.log((*i)->getDescription() + " put into tuple creation even though its inputs are not void", INTERNAL_ERROR);
}
if ((*i)->getReturnType()->matches(Void))
{
error.log((*i)->getDescription() + " put into tuple creation even though its output is void", INTERNAL_ERROR);
}
}
}
string getDescription()
{
return str::putStringInTreeNodeBox("make tuple of type "+getReturnType()->getName());
//return "[tuple of type " + getReturnType()->getString() + "]";
/*string out;
out+="\n{";
for (auto i=sourceActions.begin(); i!=sourceActions.end(); ++i)
{
out+="\n\t";
string str;
if (*i)
str=(*i)->getDescription();
else
str="[null action]";
for (unsigned j=0; j<str.size(); ++j)
{
out+=str[j];
if (str[j]=='\n')
out+='\t';
}
out+="\n";
}
out+="}\n";
return out;*/
}
void* execute(void* inLeft, void* inRight)
{
void* out=malloc(getReturnType()->getSize());
size_t offset=0;
for (auto i=sourceActions.begin(); i!=sourceActions.end(); ++i)
{
void* val=(*i)->execute(nullptr, nullptr);
memcpy((char*)out+offset, val, (*i)->getReturnType()->getSize());
free(val);
offset+=(*i)->getReturnType()->getSize();
}
return out;
}
void addToProg(Action inLeft, Action inRight, CppProgram* prog)
{
if (sourceActions.size()==1)
{
sourceActions[0]->addToProg(prog);
return;
}
prog->code(prog->getTypeCode(getReturnType()));
prog->pushExpr();
bool start=true;
for (auto i: sourceActions)
{
if (!start) prog->code(", ");
start=false;
i->addToProg(prog);
}
prog->popExpr();
}
private:
vector<Action> sourceActions;
friend GetElemFromTupleAction;
friend CppTupleCastAction;
};
class CppTupleCastAction: public ActionData
{
public:
CppTupleCastAction(Action actionIn, Type returnType):
ActionData(returnType, Void, Void)
{
if ((actionIn->getReturnType()->getType()!=TypeBase::TUPLE && getReturnType()->getType()!=TypeBase::TUPLE) || !actionIn->getReturnType()->matches(getReturnType()))
{
throw PineconeError("CppCastAction was only designed to cast matching tuples, which is not how it is being used", INTERNAL_ERROR);
}
action=actionIn;
}
string getDescription()
{
return "C++ cast";
}
void* execute(void* inLeft, void* inRight)
{
throw PineconeError("CppCastAction was executed in the interpreter, which shouldn't happen", INTERNAL_ERROR);
}
void addToProg(Action inLeft, Action inRight, CppProgram* prog)
{
if (getReturnType()->getAllSubTypes()->size()==1)
{
action->addToProg(prog);
}
else if (typeid(*action)==typeid(MakeTupleAction))
{
MakeTupleAction * realAction=(MakeTupleAction*)&*action;
prog->code(prog->getTypeCode(getReturnType()));
prog->pushExpr();
for (auto i: realAction->sourceActions)
{
i->addToProg(prog);
if (i!=realAction->sourceActions.back())
prog->code(", ");
}
prog->popExpr();
}
else if (typeid(*action)==typeid(*listAction({voidAction, voidAction}, {})))
{
addListToProgWithCppCasting((ListAction*)&*action, getReturnType(), prog);
}
else if (getReturnType()->getType()!=TypeBase::TUPLE)
{
action->addToProg(prog);
prog->code(".");
prog->code(action->getReturnType()->getAllSubTypes()[0][0].name);
}
else
{
string funcName=action->getReturnType()->getCompactString()+"=>"+getReturnType()->getCompactString();
if (!prog->hasFunc(funcName))
{
Type argType=makeTuple({{"in", action->getReturnType()}}, true);
prog->pushFunc(funcName, "", Void, argType, getReturnType());
prog->declareVar("-out", getReturnType());
auto outTypes=*getReturnType()->getAllSubTypes();
if (action->getReturnType()->getType()==TypeBase::TUPLE)
{
auto inTypes=*action->getReturnType()->getAllSubTypes();
for (int i=0; i<int(inTypes.size()); i++)
{
//if (inTypes[i].type==outTypes[i].type)
{
prog->name("-out");
prog->code(".");
prog->code(outTypes[i].name);
prog->code(" = ");
prog->name("in");
prog->code(".");
prog->code(inTypes[i].name);
prog->endln();
}
}
}
else
{
prog->name("-out");
prog->code(".");
prog->code(outTypes[0].name);
prog->code(" = ");
prog->name("in");
prog->endln();
}
prog->code("return ");
prog->name("-out");
prog->endln();
prog->popFunc();
}
prog->name(funcName);
prog->pushExpr();
action->addToProg(prog);
prog->popExpr();
}
}
private:
Action action;
friend GetElemFromTupleAction;
};
class GetElemFromTupleAction: public ActionData
{
public:
GetElemFromTupleAction(Type typeInIn, string nameIn):
ActionData(typeInIn->getSubType(nameIn).type, typeInIn, Void)
{
typeIn=typeInIn;
typeOut=typeInIn->getSubType(nameIn).type;
// if no type was found, the ActionData constructor would have already thrown an error
name=nameIn;
size=typeOut->getSize();
offset=typeIn->getSubType(name).offset;
}
string getDescription()
{
return str::putStringInTreeNodeBox(name);
//return "get element from tuple";
}
void* execute(void* inLeft, void* inRight)
{
void* out=malloc(size);
memcpy(out, (char*)inLeft+offset, size);
return out;
}
void addToProg(Action inLeft, Action inRight, CppProgram* prog)
{
if (typeIn->getAllSubTypes()->size()==1)
{
inLeft->addToProg(prog);
return;
}
MakeTupleAction * makeTupleAction=nullptr;
if (typeid(*inLeft)==typeid(MakeTupleAction))
{
makeTupleAction=(MakeTupleAction *)&*inLeft;
}
else if (typeid(*inLeft)==typeid(CppTupleCastAction))
{
Action castAction=((CppTupleCastAction *)&*inLeft)->action;
if (typeid(*castAction)==typeid(MakeTupleAction))
{
makeTupleAction=(MakeTupleAction *)&*castAction;
}
}
if (makeTupleAction)
{
auto types=*inLeft->getReturnType()->getAllSubTypes();
for (int i=0; i<int(types.size()); i++)
{
if (types[i].name==name)
{
makeTupleAction->sourceActions[i]->addToProg(prog);
break;
}
}
}
else
{
/*
if (inLeft->nameHint=="in" || inLeft->nameHint=="me")
{
prog->code(name);
}
else
*/
{
inLeft->addToProg(prog);
prog->code("."+name);
}
}
}
private:
Type typeIn;
Type typeOut;
int offset;
size_t size;
string name;
};
Action makeTupleAction(const std::vector<Action>& sourceActionsIn)
{
return Action(new MakeTupleAction(sourceActionsIn));
}
Action getElemFromTupleAction(Type source, string name)
{
if (!source->getSubType(name).type)
throw PineconeError("could not find '"+name+"' in "+source->getString(), SOURCE_ERROR);
Action out=Action(new GetElemFromTupleAction(source, name));
return out;
}
Action cppTupleCastAction(Action actionIn, Type returnType)
{
return Action(new CppTupleCastAction(actionIn, returnType));
}
================================================
FILE: src/Actions/TypeAction.cpp
================================================
#include "../../h/Action.h"
#include "../../h/ErrorHandler.h"
class TypeGetAction: public ActionData
{
public:
TypeGetAction(Type typeIn):
ActionData(typeIn->getMeta(), Void, Void)
{
setDescription(typeIn->getString()+" (type)");
}
string getCSource(string inLeft, string inRight)
{
return "/* C source for TypeGetAction not yet implemented */";
}
void* execute(void* inLeft, void* inRight)
{
error.log("TypeGetAction::execute called, which shouldn't happen", RUNTIME_ERROR);
return nullptr;
}
string getDescription()
{
return str::putStringInTreeNodeBox("{"+getReturnType()->getName()+"}");
}
private:
};
Action typeGetAction(Type typeIn)
{
return Action(new TypeGetAction(typeIn));
}
================================================
FILE: src/Actions/VarAction.cpp
================================================
#include "../../h/Action.h"
#include "../../h/ErrorHandler.h"
#include "../../h/StackFrame.h"
#include "../../h/CppProgram.h"
#include "../../h/utils/stringNumConversion.h"
#include "../../h/Namespace.h"
#include "../../h/utils/stringDrawing.h"
class VarGetAction: public ActionData
{
public:
VarGetAction(size_t in, void ** stackPtrPtrIn, Type typeIn, string idIn):
ActionData(typeIn, Void, Void)
{
offset=in;
stackPtrPtr=stackPtrPtrIn;
nameHint=idIn;
setDescription("get " + typeIn->getString() + " '" + idIn + "'");
}
void* execute(void* inLeft, void* inRight)
{
if (!(*stackPtrPtr))
{
throw PineconeError("something fucked up big time. VarGetAction::execute called while stack pointer is still null", RUNTIME_ERROR);
}
void* out=malloc(returnType->getSize());
memcpy(out, (char*)(*stackPtrPtr)+offset, returnType->getSize());
return out;
}
void addToProg(Action inLeft, Action inRight, CppProgram* prog)
{
/*
if ((nameHint=="me" || nameHint=="in") && getReturnType()->getType()==TypeBase::TUPLE)
{
prog->code(prog->getTypeCode(getReturnType()));
prog->pushExpr();
bool isFirst=true;
for (auto i: *getReturnType()->getAllSubTypes())
{
if (!isFirst)
prog->code(", ");
isFirst=false;
prog->name(i.name);
}
prog->popExpr();
}
else
*/
{
prog->declareVar(nameHint, getReturnType());
prog->name(nameHint);
}
}
string getDescription()
{
return str::putStringInTreeNodeBox("get "+nameHint);
}
private:
void ** stackPtrPtr;
size_t offset;
};
class VarSetAction: public ActionData
{
public:
VarSetAction(size_t in, void ** stackPtrPtrIn, Type typeIn, string idIn):
ActionData(Void, Void, typeIn)
{
offset=in;
stackPtrPtr=stackPtrPtrIn;
nameHint=idIn;
setDescription("set " + typeIn->getString() + " '" + idIn + "'");
}
void* execute(void* left, void* right)
{
if (!(*stackPtrPtr))
{
throw PineconeError("something fucked up big time. VarSetAction::execute called while stack pointer is still null", RUNTIME_ERROR);
}
//copy data on to the stack location of the var
memcpy((char*)(*stackPtrPtr)+offset, right, inRightType->getSize());
//return a new copy of the data
void* out=malloc(returnType->getSize());
memcpy(out, (char*)(*stackPtrPtr)+offset, inRightType->getSize());
//return out;
return nullptr;
}
void addToProg(Action inLeft, Action inRight, CppProgram* prog)
{
/*
if ((nameHint=="me" || nameHint=="in") && getReturnType()->getType()==TypeBase::TUPLE)
{
if (prog->getExprLevel()>0)
{
throw PineconeError("can not set 'in' or 'me' inside expression in C++ because of some really dumb reason", INTERNAL_ERROR);
}
prog->pushBlock();
prog->code(prog->getTypeCode(inRight->getReturnType()));
prog->code(" tmp = ");
prog->pushExpr();
inRight->addToProg(prog);
prog->popExpr();
prog->endln();
auto subs=*getReturnType()->getAllSubTypes();
for (int i=0; i<(int)subs.size(); i++)
{
prog->name(subs[i].name);
prog->code(" = ");
prog->code("tmp."+(*inRight->getReturnType()->getAllSubTypes())[i].name);
//prog->pushExpr();
//getElemFromTupleAction(inRight->getReturnType(), (*inRight->getReturnType()->getAllSubTypes())[i].name)->addToProg(var, voidAction, prog);
//prog->popExpr();
prog->endln();
}
prog->popBlock();
}
else
*/
{
prog->declareVar(nameHint, getInRightType());
prog->name(nameHint);
prog->code(" = ");
prog->pushExpr();
inRight->addToProg(prog);
prog->popExpr();
//if (prog->getExprLevel()==0)
// prog->endln();
}
}
string getDescription()
{
return str::putStringInTreeNodeBox("set "+nameHint);
}
private:
void ** stackPtrPtr;
size_t offset;
};
class ConstGetAction: public ActionData
{
public:
ConstGetAction(const void* in, Type typeIn, string textIn):
ActionData(typeIn, Void, Void)
{
data=malloc(returnType->getSize());
memcpy(data, in, returnType->getSize());
setDescription(textIn);// + " (" + typeIn.toString() + " literal)");
}
~ConstGetAction()
{
free(data);
}
void* execute(void* inLeft, void* inRight)
{
void* out=malloc(returnType->getSize());
memcpy(out, data, returnType->getSize());
return out;
}
void addToProg(Action inLeft, Action inRight, CppProgram* prog)
{
if (getReturnType()==String)
{
//addToProgPnStr(prog);
//prog->name("$pnStr");
prog->code(prog->getTypeCode(String));
prog->pushExpr();
auto sizeInfo=getReturnType()->getSubType("_size");
auto dataInfo=getReturnType()->getSubType("_data");
if (sizeInfo.type!=Int || dataInfo.type!=Byte->getPtr())
{
throw PineconeError("ConstGetAction::addToProg failed to access string properties", INTERNAL_ERROR);
}
prog->code(Int->getCppLiteral((char*)data+sizeInfo.offset, prog));
prog->code(", ");
//prog->code(Int->getCppLiteral((char*)data+sizeInfo.offset, prog));
//prog->code(", (unsigned char*)\"");
prog->code("(unsigned char*)\"");
int len=*(int*)((char*)data+sizeInfo.offset);
for (int i=0; i<len; i++)
{
char c=*((*(char**)((char*)data+dataInfo.offset))+i);
if (c=='"')
{
prog->code("\\\"");
}
else if (c=='\\')
{
prog->code("\\\\");
}
else if (c>=32 && c<=126)
{
prog->code(string()+c);
}
else if (c=='\n')
{
prog->code("\\n");
}
else
{
prog->code(str::charToCppStringLiteralEscaped(c));
}
}
prog->code("\"");
prog->popExpr();
}
else
{
prog->code(getReturnType()->getCppLiteral(data, prog));
}
}
string getDescription()
{
return str::putStringInTreeNodeBox(description);
}
private:
void* data;
};
Action varGetAction(size_t in, Type typeIn, string textIn)
{
return Action(new VarGetAction(in, &stackPtr, typeIn, textIn));
}
Action varSetAction(size_t in, Type typeIn, string varNameIn)
{
return Action(new VarSetAction(in, &stackPtr, typeIn, varNameIn));
}
Action globalGetAction(size_t in, Type typeIn, string textIn)
{
return Action(new VarGetAction(in, &globalFramePtr, typeIn, textIn));
}
Action globalSetAction(size_t in, Type typeIn, string textIn)
{
return Action(new VarSetAction(in, &globalFramePtr, typeIn, textIn));
}
Action constGetAction(const void* in, Type typeIn, string textIn, Namespace ns)
{
Action action=Action(new ConstGetAction(in, typeIn, textIn));
if (ns)
{
Action copier=ns->getCopier(typeIn);
if (copier)
action=branchAction(voidAction, copier, action);
}
return action;
}
================================================
FILE: src/AllOperators.cpp
================================================
#include "../h/AllOperators.h"
#include "../h/ErrorHandler.h"
//shared_ptr<AllOperators> ops(nullptr);
AllOperators* ops=nullptr;
Operator opCreate(string textIn, int leftPrecedenceIn, int rightPrecedenceIn, bool overloadableIn);
void AllOperators::init()
{
//ops=shared_ptr<AllOperators>(new AllOperators());
ops=new AllOperators();
}
AllOperators::AllOperators()
{
#undef DECLARE_OP
//#define DECLARE_OP(name, text, left, right, overload) putOpInMap(name);
#define DECLARE_OP(name, text, prece, input, overload) putOpInMap(name);
ALL_OPS;
}
void AllOperators::putOpInMap(Operator op)
{
opsMap[op->getText()]=op;
}
void AllOperators::get(string text, vector<Operator>& out)
{
int start=0;
int end=text.size();
while (start<int(text.size()))
{
while (true)
{
if (end<=start)
{
error.log("unknown operator '" + text + "'", SOURCE_ERROR);
}
auto i=opsMap.find(text.substr(start, end-start));
if (i==opsMap.end())
{
end--;
}
else
{
out.push_back(i->second);
start=end;
end=text.size();
break;
}
}
}
}
bool AllOperators::isOpenBrac(Operator op)
{
return op==openPeren || op==openSqBrac || op==openCrBrac;
}
bool AllOperators::isCloseBrac(Operator op)
{
return op==closePeren || op==closeSqBrac || op==closeCrBrac;
}
/*
// 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
Operator opCreate(string textIn, int leftPrecedenceIn, int rightPrecedenceIn, bool overloadableIn)
{
Operator ptr(new OperatorData(textIn, leftPrecedenceIn, rightPrecedenceIn, overloadableIn));
for (auto i=OperatorData::precedenceLevels.begin();; i++)
{
if (i==OperatorData::precedenceLevels.end() || *i>leftPrecedenceIn)
{
OperatorData::precedenceLevels.insert(i, leftPrecedenceIn);
break;
}
else if (*i==leftPrecedenceIn)
break;
}
for (auto i=OperatorData::precedenceLevels.begin();; i++)
{
if (i==OperatorData::precedenceLevels.end() || *i>rightPrecedenceIn)
{
OperatorData::precedenceLevels.insert(i, rightPrecedenceIn);
break;
}
else if (*i==rightPrecedenceIn)
break;
}
//operators.push_back(ptr);
return ptr;
}
*/
================================================
FILE: src/AstNode.cpp
================================================
#include "../h/AstNode.h"
#include "../h/Namespace.h"
#include "../h/ErrorHandler.h"
#include "../h/msclStringFuncs.h"
#include "../h/utils/stringDrawing.h"
#include "../h/AllOperators.h"
//AstNode astVoid=AstNode(new AstVoid);
extern StackFrame stdLibStackFrame;
extern Namespace globalNamespace;
Action resolveLiteral(Token token);
void AstNodeBase::copyToNode(AstNodeBase* other, bool copyCache)
{
other->inLeftType=inLeftType;
other->inRightType=inRightType;
other->nameHint=nameHint;
if (copyCache)
{
other->action=action;
other->returnType=returnType;
other->dynamic=dynamic;
other->ns=ns;
other->inputHasBeenSet=inputHasBeenSet;
}
}
/// List
string AstList::getString()
{
vector<string> data;
for (int i=0; i<int(nodes.size()); i++)
{
data.push_back(nodes[i]->getString());
}
return str::makeList(data);
}
/*void AstList::resolveReturnType()
{
if (nodes.empty())
{
returnType=Void;
}
else
{
nodes.back()->setInput(ns, dynamic, Void, Void);
returnType=nodes.back()->getReturnType();
}
}*/
void AstList::resolveAction()
{
if (!inLeftType->isVoid() || !inRightType->isVoid())
{
throw PineconeError("AstList given non void input", INTERNAL_ERROR, getToken());
}
ns=ns->makeChild();
for (int i=0; i<int(nodes.size()); i++)
{
nodes[i]->setInput(ns, dynamic, Void, Void);
nodes[i]->dealWithConstants();
}
vector<Action> actions;
for (int i=0; i<int(nodes.size()); i++)
{
try
{
Action action=nodes[i]->getAction();
if (i!=(int)nodes.size()-1)
action=ns->wrapInDestroyer(action);
actions.push_back(action);
}
catch (PineconeError err)
{
err.log();
}
}
action=listAction(actions, *ns->getDestroyerActions());
}
/// Function body
string AstFuncBody::getString()
{
vector<string> data;
data.push_back("function");
vector<string> types={leftTypeNode->getString(), rightTypeNode->getString(), returnTypeNode->getString()};
data.push_back(str::makeList(types));
data.push_back(bodyNode->getString());
return str::makeList(data);
}
AstNode AstFuncBody::makeCopyWithSpecificTypes(Type leftInType, Type rightInType)
{
Type leftWhatevType=leftTypeNode->getReturnType()->getSubType();
Type rightWhatevType=rightTypeNode->getReturnType()->getSubType();
if (!leftInType->matches(leftWhatevType) || !rightInType->matches(rightWhatevType))
{
return nullptr;
}
AstNode actualLeftTypeNode;
AstNode actualRightTypeNode;
if (leftWhatevType->isWhatev())
{
actualLeftTypeNode=AstTypeType::make(leftWhatevType->actuallyIs(leftInType));
}
else
{
actualLeftTypeNode=leftTypeNode->makeCopy(false);
}
if (rightWhatevType->isWhatev())
{
actualRightTypeNode=AstTypeType::make(rightWhatevType->actuallyIs(rightInType));
}
else
{
actualRightTypeNode=rightTypeNode->makeCopy(false);
}
AstNode out=make(move(actualLeftTypeNode), move(actualRightTypeNode), returnTypeNode->makeCopy(false), bodyNode->makeCopy(false));
out->nameHint=nameHint;
out->setInput(ns, dynamic, Void, Void);
return out;
}
void AstFuncBody::resolveAction()
{
setTypesInput();
Namespace subNs=ns->makeChildAndFrame(nameHint.empty()?"unnamed function's namespace":nameHint+"'s namespace");
subNs->setInput(leftTypeNode->getReturnType()->getSubType(), rightTypeNode->getReturnType()->getSubType());
bodyNode->setInput(subNs, true, Void, Void);
Type funcReturnType=returnTypeNode->getReturnType()->getSubType();
if (funcReturnType->isWhatev())
{
funcReturnType=funcReturnType->actuallyIs(bodyNode->getReturnType());
}
action=functionAction(bodyNode->makeCopy(true), funcReturnType, subNs->getStackFrame());
}
/// Expression
string AstExpression::getString()
{
string leftStr;
if (!leftIn->isVoid())
{
leftStr=leftIn->getString();
}
string centerStr=center->getString();
string rightStr;
if (!rightIn->isVoid())
{
rightStr=rightIn->getString();
}
return str::makeRootUpBinaryTree(centerStr, "", "", leftStr, rightStr);
}
void AstExpression::resolveAction()
{
if (!inLeftType->isVoid() || !inRightType->isVoid())
{
throw PineconeError("AstExpression given non void input", INTERNAL_ERROR, getToken());
}
if (rightIn->isType())
{
throw PineconeError("types must be declared as constants", SOURCE_ERROR, rightIn->getToken());
}
else if (center->isType() || center->isFunctionWithOutput() || leftIn->isType())
{
throw PineconeError("a function implementation got into an expression node somehow", INTERNAL_ERROR, center->getToken());
}
else
{
leftIn->setInput(ns, dynamic, Void, Void);
rightIn->setInput(ns, dynamic, Void, Void);
center->setInput(ns, dynamic, leftIn->getReturnType(), rightIn->getReturnType());
//error.log("left: " + leftIn->getString(), JSYK);
//error.log("center: " + center->getString(), JSYK);
//error.log("right: " + rightIn->getString(), JSYK);
//error.log("", JSYK);
action=branchAction(leftIn->getAction(), center->getAction(), rightIn->getAction());
}
if (action->nameHint.empty())
action->nameHint=nameHint;
}
/// Const Expression
string AstConstExpression::getString()
{
string centerStr=center->getString();
string rightStr;
if (!rightIn->isVoid())
{
rightStr=rightIn->getString();
}
return str::makeRootUpBinaryTree(centerStr, "", "const", "", rightStr);
}
void AstConstExpression::resolveConstant()
{
if (!inLeftType->isVoid() || !inRightType->isVoid())
{
throw PineconeError("AstConstExpression given non void input", INTERNAL_ERROR, getToken());
}
//leftIn->setInput(ns, Void, Void);
rightIn->setInput(ns, false, Void, Void);
//error.log("resolveAction called for "+getString(), JSYK);
ns->addNode(move(rightIn->makeCopy(true)), center->token->getText());
/*
Action rightAction=rightIn->getAction();
void * val=rightAction->execute(nullptr, nullptr);
//center->setInput(ns, false, Void, rightIn->getReturnType());
Action valAction=constGetAction(val, rightAction->getReturnType(), "const expression");
ns->addAction(valAction, center->token->getText());*/
}
/// Operation with input
string AstOpWithInput::getString()
{
string left;
vector<string> data;
for (int i=0; i<int(leftIn.size()); i++)
{
data.push_back(leftIn[i]->getString());
}
if (data.size()==1)
left=data[0];
else if (data.size()>1)
left=str::makeList(data);
data.clear();
string right;
for (int i=0; i<int(rightIn.size()); i++)
{
data.push_back(rightIn[i]->getString());
}
if (data.size()==1)
right=data[0];
else if (data.size()>1)
right=str::makeList(data);
return str::makeRootUpBinaryTree(str::putStringInTreeNodeBox(token->getText()), "", "", left, right);
}
void AstOpWithInput::resolveAction()
{
if (token->getOp()==ops->ifOp)
{
for (int i=0; i<int(leftIn.size()); i++)
leftIn[i]->setInput(ns, dynamic, Void, Void);
for (int i=0; i<int(rightIn.size()); i++)
rightIn[i]->setInput(ns, dynamic, Void, Void);
if (leftIn.empty())
{
throw PineconeError("'?' must have a conditional to its left", SOURCE_ERROR, token);
}
else if (leftIn.size()!=1)
{
throw PineconeError("'?' can only have one conditional to its left", SOURCE_ERROR, token);
}
Action condition=leftIn[0]->getAction();
if (rightIn.empty())
{
throw PineconeError("'?' must have a statement to its right", SOURCE_ERROR, token);
}
else if (rightIn.size()<=2)
{
Action a;
try
{
a=rightIn[0]->getAction();
}
catch (PineconeError err)
{
err.log();
a=voidAction;
}
if (rightIn.size()==1)
{
action=ifAction(condition, a);
}
else
{
Action e;
try
{
e=rightIn[1]->getAction();
}
catch (PineconeError err)
{
err.log();
e=voidAction;
}
action=ifElseAction(condition, a, e);
}
}
else
{
throw PineconeError("'?' can only have 1 or 2 '|' seporated expressions to its right", SOURCE_ERROR, token);
}
}
else if (token->getOp()==ops->loop)
{
bool usesSubNS=false;
if (leftIn.size()==3)
{
ns=ns->makeChild();
usesSubNS=true;
}
for (int i=0; i<int(leftIn.size()); i++)
leftIn[i]->setInput(ns, dynamic, Void, Void);
for (int i=0; i<int(rightIn.size()); i++)
rightIn[i]->setInput(ns, dynamic, Void, Void);
Action initAction=nullptr, conditionAction, endAction, bodyAction;
if (rightIn.size()>1)
{
throw PineconeError("'@' followed by multiple expressions", SOURCE_ERROR, token);
}
if (leftIn.size()==0)
{
throw PineconeError("condition needed before '@'", SOURCE_ERROR, token);
}
else if (leftIn.size()==1)
{
conditionAction=leftIn[0]->getAction();
endAction=voidAction;
}
else if (leftIn.size()==2)
{
conditionAction=leftIn[0]->getAction();
endAction=leftIn[1]->getAction();
}
else if (leftIn.size()==3)
{
initAction=leftIn[0]->getAction();
conditionAction=leftIn[1]->getAction();
endAction=leftIn[2]->getAction();
}
else
{
throw PineconeError("chain of length "+to_string(leftIn.size())+"preceding '@', it should be length 1-3", SOURCE_ERROR, token);
}
if (rightIn.empty())
{
bodyAction=voidAction;
}
else
{
try
{
bodyAction=rightIn[0]->getAction();
}
catch (PineconeError err)
{
err.log();
bodyAction=voidAction;
}
}
vector<Action> actions;
if (initAction)
actions.push_back(ns->wrapInDestroyer(initAction));
actions.push_back(ns->wrapInDestroyer(loopAction(conditionAction, endAction, bodyAction)));
action=usesSubNS ?
action=listAction(actions, *ns->getDestroyerActions())
:
action=listAction(actions, {})
;
}
else if (token->getOp()==ops->andOp || token->getOp()==ops->orOp)
{
if (leftIn.size()>1 || rightIn.size()>1)
{
throw PineconeError("'"+token->getOp()->getText()+"' can not be sent '|' separated sequence", SOURCE_ERROR, getToken());
}
if (leftIn.size()!=1 || rightIn.size()!=1)
{
throw PineconeError("'"+token->getOp()->getText()+"' must be given a left and right input", SOURCE_ERROR, getToken());
}
leftIn[0]->setInput(ns, dynamic, Void, Void);
rightIn[0]->setInput(ns, dynamic, Void, Void);
Action leftAction=leftIn[0]->getAction();
Action rightAction=rightIn[0]->getAction();
if (leftAction->getReturnType()!=Bool)
{
throw PineconeError("'"+token->getOp()->getText()+"' can only be used with Bools", SOURCE_ERROR, leftIn[0]->getToken());
}
if (rightAction->getReturnType()!=Bool)
{
throw PineconeError("'"+token->getOp()->getText()+"' can only be used with Bools", SOURCE_ERROR, rightIn[0]->getToken());
}
if (token->getOp()==ops->andOp)
{
action=andAction(leftAction, rightAction);
}
else // (token->getOp()==ops->orOp)
{
action=orAction(leftAction, rightAction);
}
}
else if (token->getOp()==ops->rightArrow)
{
throw PineconeError("AstOpWithInput::resolveAction called for token '"+token->getOp()->getText()+"', which it shouldn't have been", INTERNAL_ERROR, token);
}
else
{
throw PineconeError("AstOpWithInput made with bad token '"+token->getText()+"'", INTERNAL_ERROR, token);
}
}
bool AstOpWithInput::isFunctionWithOutput()
{
return token->getOp()==ops->rightArrow && leftIn.size()==1 && rightIn.size()==1;
}
/// Token
string AstToken::getString()
{
return str::putStringInTreeNodeBox(token->getText());
}
void AstToken::resolveAction()
{
//error.log("resolveAction called for token "+token->getText(), JSYK, token);
if (token->getType()==TokenData::IDENTIFIER || token->getType()==TokenData::OPERATOR)
{
if (token->getOp() && !token->getOp()->isOverloadable())
{
throw PineconeError("non overloadable operator in AstToken, it should have been removed and processed by the parser", INTERNAL_ERROR, token);
}
/*
if (inLeftType->getType()==TypeBase::TUPLE && inLeftType->getSubType(token->getText()).type!=nullptr)
{
if (inRightType->isVoid())
{
action=getElemFromTupleAction(inLeftType, token->getText());
return;
}
else
{
throw PineconeError("sorry, Pinecone does not yet support mutating tuples", SOURCE_ERROR, token);
}
}
*/
action=ns->getActionForTokenWithInput(token, inLeftType, inRightType, dynamic, true, token);
/*
try
{
//error.log("looking for "+token->getText()+" in\n"+ns->getStringWithParents(), JSYK, token);
action=ns->getActionForTokenWithInput(token, inLeftType, inRightType, dynamic);
}
catch (IdNotFoundError err)
{
if (token->getType()==TokenData::OPERATOR)
{
throw PineconeError("unknown overload for "+inLeftType->getString()+" "+token->getText()+" "+inRightType->getString()+"'", SOURCE_ERROR, token);
}
else if (token->getType()==TokenData::IDENTIFIER)
{
vector<Action> actions;
ns->getActions(token->getText(), actions, dynamic);
if (actions.size()>0) // if there are actions with the requested name that didn't match the type
{
string posibleInputs="the following is the inputs it can take:";
for (int i=0; i<(int)actions.size(); i++)
{
posibleInputs+="\n ";
posibleInputs+=actions[i]->getInLeftType()->getString()+" . "+actions[i]->getInRightType()->getString()+" -> "+actions[i]->getReturnType()->getString();
}
throw PineconeError(
"'"+token->getText()+"' can not take input of type "+
inLeftType->getString()+" . "+inRightType->getString()+"\n"+
posibleInputs,
SOURCE_ERROR, token);
}
}
if (inRightType->getType()==TypeBase::METATYPE)
{
throw PineconeError("metatype handeling in "+FUNC+" not yet implemented", INTERNAL_ERROR, token);
}
else if (inRightType->isVoid())
{
//throw PineconeError("unknown identifier '"+token->getText()+"' (var can not be made bc right in type is "+type->getString()+")", SOURCE_ERROR, token);
throw PineconeError("unknown identifier '"+token->getText()+"'", SOURCE_ERROR, token);
}
else if (!inRightType->isCreatable())
{
throw PineconeError("cannot create variable '"+token->getText()+"' of type {"+inRightType->getString()+"}", SOURCE_ERROR, token);
}
ns->addVar(inRightType, token->getText());
try
{
action=ns->getActionForTokenWithInput(token, inLeftType, inRightType, dynamic);
}
catch (IdNotFoundError err)
{
throw err.toPineconeError(token);
}
}
*/
}
else if (token->getType()==TokenData::LITERAL || token->getType()==TokenData::STRING_LITERAL)
{
if (!inLeftType->isVoid() || !inRightType->isVoid())
{
throw PineconeError("a literal can not be given an input", SOURCE_ERROR, token);
}
action=resolveLiteral(token);
}
else
{
throw PineconeError("AstToken givin invalid token '"+token->getText()+"' of type "+TokenData::typeToString(token->getType()), INTERNAL_ERROR, token);
}
}
/// Tuple
string AstTuple::getString()
{
vector<string> data;
for (int i=0; i<int(nodes.size()); i++)
{
data.push_back(nodes[i]->getString());
}
return str::makeList(data);
}
void AstTuple::resolveAction()
{
vector<Action> actions;
for (int i=0; i<int(nodes.size()); i++)
{
nodes[i]->setInput(ns, dynamic, Void, Void);
actions.push_back(nodes[i]->getAction());
}
action=makeTupleAction(actions);
}
/// TokenType
string AstTokenType::getString()
{
return "{"+token->getText()+"}";
}
void AstTokenType::resolveReturnType()
{
returnType=ns->getType(token->getText(), true, token)->getMeta();
}
/// TupleType
string AstTupleType::getString()
{
string out;
out+="AstTupleType{";
for (int i=0; i<int(subTypes.size()); i++)
{
auto type=&subTypes[i];
if (type->name)
{
out+=type->name->getText()+": ";
}
out+=type->type->getString();
if (i<int(subTypes.size())-1)
{
out+=", ";
}
}
out+="}";
return out;
}
void AstTupleType::resolveReturnType()
{
TupleTypeMaker maker;
for (unsigned i=0; i<subTypes.size(); i++)
{
subTypes[i].type->setInput(ns, false, Void, Void);
if (subTypes[i].name)
{
maker.add(subTypes[i].name->getText(), subTypes[i].type->getReturnType()->getSubType());
}
else
{
maker.add(subTypes[i].type->getReturnType()->getSubType());
}
}
returnType=maker.get(true)->getMeta();
}
================================================
FILE: src/CppProgram.cpp
================================================
#include "../h/CppProgram.h"
#include "../h/msclStringFuncs.h"
#include <map>
#include <unordered_set>
string getValidCppId(string in)
{
string cpp;
if (in.empty())
in="no_name";
int start=0;
// all this should work with unicode (although it may inject random (but valid) characters into the C++ names)
do
{
int i=start;
for (; i<int(in.size()) && (
(in[i]>='a' && in[i]<='z') ||
(in[i]>='A' && in[i]<='Z') ||
(in[i]>='0' && in[i]<='9') ||
in[i]=='_'
); i++) {}
if (i!=start)
{
if (in[start]>='0' && in[start]<='9')
cpp+="_";
cpp+=in.substr(start, i-start);
}
start=i+1;
} while (start<int(in.size()));
return cpp;
}
/// Name Container
CppNameContainer::CppNameContainer()
{
}
shared_ptr<CppNameContainer> CppNameContainer::makeRoot()
{
auto out=shared_ptr<CppNameContainer>(new CppNameContainer());
out->parent=nullptr;
return out;
}
shared_ptr<CppNameContainer> CppNameContainer::makeChild()
{
auto out=shared_ptr<CppNameContainer>(new CppNameContainer());
children.push_back(out);
out->parent=this;
return out;
}
void CppNameContainer::addPn(const string& pn, const string& cppNameHint)
{
string validCppHint;
if (cppNameHint=="<- the value of that pn string please")
validCppHint=getValidCppId(pn);
else if (!cppNameHint.empty())
validCppHint=getValidCppId(cppNameHint);
if (pnToCppMap.find(pn)!=pnToCppMap.end())
{
throw PineconeError("Tried to add '"+pn+"' as a pn name to a CppNameContainer but that pn name already exists", INTERNAL_ERROR);
}
// 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
string cpp;
if (validCppHint.empty())
{
cpp=getUniqueString(
"nm",
[this](string in) -> bool
{
return !hasCpp(in);
},
true
);
}
else
{
cpp=getUniqueString(
validCppHint,
[this](string in) -> bool
{
return !hasCpp(in);
},
false
);
}
pnToCppMap[pn]=cpp;
cppSet.insert(cpp);
}
void CppNameContainer::reserveCpp(const string& cpp, bool ignoreCollisions)
{
if (!ignoreCollisions && hasCpp(cpp))
{
throw PineconeError("called CppNameContainer::reserveCpp with id '"+cpp+"', which already exists", INTERNAL_ERROR);
}
cppSet.insert(cpp);
}
bool CppNameContainer::hasPnMe(const string& pn)
{
return pnToCppMap.find(pn)!=pnToCppMap.end();
}
bool CppNameContainer::hasPn(const string& pn)
{
return hasPnMe(pn) || (parent && parent->hasPn(pn));
}
bool CppNameContainer::hasCpp(const string& cpp)
{
return hasCppMe(cpp) || hasCppUp(cpp) || hasCppDown(cpp);
}
bool CppNameContainer::hasCppMe(const string& cpp)
{
return cppSet.find(cpp)!=cppSet.end();
}
bool CppNameContainer::hasCppUp(const string& cpp)
{
return parent && (parent->hasCppMe(cpp) || parent->hasCppUp(cpp));
}
bool CppNameContainer::hasCppDown(const string& cpp)
{
for (auto i: children)
{
if (i->hasCppMe(cpp) || i->hasCppDown(cpp))
return true;
}
return false;
}
string CppNameContainer::getCpp(const string& pn)
{
auto result=pnToCppMap.find(pn);
if (result==pnToCppMap.end())
{
if (parent)
return parent->getCpp(pn);
else
throw PineconeError("could not find C++ equivalent of '"+pn+"' in CppNameContainer::getCppForPn", INTERNAL_ERROR);
}
else
return result->second;
}
/// funcs
CppFuncBase::CppFuncBase(string prototypeIn, shared_ptr<CppNameContainer> myNames, bool returnsValIn)
{
prototype=prototypeIn;
namespaceStack.push_back(myNames);
freshLine=true;
returnsVal=returnsValIn;
}
void CppFuncBase::code(const string& in)
{
if (freshLine)
{
source+=indentString(in, indent, blockLevel);
freshLine=(in.back()=='\n');
}
else if (searchInString(in, "\n")>0)
{
source+="\n"+indentString(in, indent, blockLevel);
if (in.back()!='\n')
source+="\n";
freshLine=true;
}
else
{
source+=in;
freshLine=(in.back()=='\n');
}
}
void CppFuncBase::name(const string& in)
{
code(namespaceStack.back()->getCpp(in));
}
void CppFuncBase::line(const string& in)
{
code(in);
endln();
}
void CppFuncBase::endln()
{
if (exprLevel>0)
{
throw PineconeError("non zero expression level when ending line in C++ program, code so far:\n"+indentString(source), INTERNAL_ERROR);
}
else if (freshLine && (source.size()<2 || source[source.size()-2]==';' || source[source.size()-2]=='}' || source[source.size()-2]=='{'))
{
// do nothing
//source+=indentString("\n", indent, blockLevel);
}
else
{
source+=";\n";
}
freshLine=true;
}
void CppFuncBase::comment(const string& in)
{
if (searchInString(in, "\n")>=0)
{
source+=indentString("\n/*\n"+in+"\n*/\n", indent, blockLevel);
freshLine=true;
}
else if (exprLevel>0 || !freshLine)
{
source+="/* "+in+" */";
freshLine=false;
}
else
{
source+=indentString("// "+in+"\n", indent, blockLevel);
freshLine=true;
}
};
void CppFuncBase::pushExpr()
{
code("(");
exprLevel++;
freshLine=false;
}
void CppFuncBase::popExpr()
{
if (exprLevel<=0)
{
throw PineconeError("CppProgram::popExpression called with zero expressionLevel", INTERNAL_ERROR);
}
code(")");
exprLevel--;
freshLine=false;
}
void CppFuncBase::pushBlock()
{
if (exprLevel>0)
{
throw PineconeError("CppProgram::pushBlock called when expressionLevel was not zero", INTERNAL_ERROR);
}
{
code("{\n");
namespaceStack.push_back(namespaceStack.back()->makeChild());
blockLevel++;
freshLine=true;
}
}
void CppFuncBase::popBlock()
{
{
if (blockLevel<=0)
{
throw PineconeError("CppProgram::popBlock called with zero indentationLevel", INTERNAL_ERROR);
}
blockLevel--;
namespaceStack.pop_back();
code("}\n");
freshLine=true;
}
}
string CppFuncBase::pnToCpp(const string& in)
{
return namespaceStack.back()->getCpp(in);
}
/// program
CppProgram::CppProgram()
{
//funcs = unique_ptr<std::map<string, CppFunc>>(new std::map<string, CppFunc>());
globalNames=CppNameContainer::makeRoot();
setup();
}
void CppProgram::setup()
{
globalTopCode+="// this C++ code is transpiled from Pinecone\n";
globalTopCode+="// Pinecone v"+to_string(VERSION_X)+"."+to_string(VERSION_Y)+"."+to_string(VERSION_Z)+" was used\n";
globalIncludesCode+="#include <string.h>\n";
globalIncludesCode+="#include <stdlib.h>\n";
globalIncludesCode+="#include <stdio.h>\n";
globalVarCode+="int argc = 0;\n";
globalVarCode+="char** argv = 0;\n";
vector<string> cppReservedWords
{
// from C
"auto", "const", "double", "float", "int", "short", "struct", "unsigned", "break",
"continue", "else", "for", "long", "signed", "switch", "void", "case", "default",
"enum", "goto", "register", "sizeof", "typedef", "volatile", "char", "do", "extern",
"if", "return", "static", "union", "while",
// from old C++
"asm", "dynamic_cast", "namespace", "reinterpret_cast", "try", "bool", "explicit",
"new", "static_cast", "typeid", "catch", "false", "operator", "template", "typename",
"class", "friend", "private", "this", "using", "const_cast", "inline", "public",
"throw", "virtual", "delete", "mutable", "protected", "true", "wchar_t",
// from C++11
"and", "bitand", "compl", "not_eq", "or_eq", "xor_eq", "and_eq", "bitor", "not", "or",
"xor",
// something else
"endl", "INT_MIN", "std", "INT_MAX", "MAX_RAND", "NULL",
// my custom
"main", "argc", "argv",
};
/*
{
"and", "and_eq", "asm", "auto", "bitand", "bitor", "bool", "break", "case", "catch", "char", "class", "const", "const_cast",
"continue", "default", "delete", "do", "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", "float",
"for", "friend", "goto", "if", "inline", "int", "long", "mutable", "namespace", "new", "not", "not_eq", "operator", "or", "or_eq",
"private", "protected", "public", "register", "reinterpret_cast", "return", "short", "signed", "sizeof", "static", "static_cast",
"struct", "switch", "template", "this", "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned", "using",
"virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq", ""
};
*/
for (auto i: cppReservedWords)
{
globalNames->reserveCpp(i);
}
pushFunc(string("_main"), Void, Void, Void);
}
string CppProgram::getTypeCode(Type in)
{
switch (in->getType())
{
case TypeBase::VOID:
return "void";
case TypeBase::DUB:
return "double";
case TypeBase::INT:
return "int";
case TypeBase::BYTE:
return "unsigned char";
case TypeBase::BOOL:
return "bool";
case TypeBase::PTR:
if (in->getSubType()->isWhatev())
return "void *";
else
return getTypeCode(in->getSubType())+" *";
case TypeBase::TUPLE:
{
if (in->getAllSubTypes()->size()==1)
return getTypeCode((*in->getAllSubTypes())[0].type);
string compact="{"+in->getCompactString()+"}";
if (!globalNames->hasPn(compact))
{
globalNames->addPn(compact, in->nameHint);
string code;
code+="struct ";
code+=globalNames->getCpp(compact);
code+="\n{\n";
for (auto i: *in->getAllSubTypes())
{
code+=indentString(getTypeCode(i.type)+" "+i.name+";\n", indent);
}
code+="\n";
code+=indentString(globalNames->getCpp(compact), indent);
code+="() {}\n";
code+="\n";
auto conNames=globalNames->makeChild();
code+=indentString(globalNames->getCpp(compact), indent);
code+="(";
bool first=true;
for (auto i: *in->getAllSubTypes())
{
if (first) first=false; else code+=", ";
conNames->addPn("+"+i.name+"_in");
code+=getTypeCode(i.type)+" "+conNames->getCpp("+"+i.name+"_in");
}
code+=")\n";
code+=indentString("{\n", indent);
for (auto i: *in->getAllSubTypes())
{
code+=indentString(i.name+" = "+conNames->getCpp("+"+i.name+"_in")+";\n", indent, 2);
}
code+=indentString("}\n", indent);
code+="};\n";
if (!globalTypesCode.empty())
globalTypesCode+="\n";
globalTypesCode+=code;
}
return globalNames->getCpp(compact);
}
default:
throw PineconeError("CppProgram::getTypeCode called with invalid type "+(TypeBase::getString(in->getType())), INTERNAL_ERROR);
}
}
void CppProgram::declareVar(const string& nameIn, Type typeIn, string initialValue)
{
/*
CppNameContainer* names=&*activeFunc->namespaceStack.back();
while (names)
{
if (names->hasPnMe(nameIn))
return;
names=names->getParent();
}
*/
if (isMain())
{
declareGlobal(nameIn, typeIn, initialValue);
return;
}
if (activeFunc->namespaceStack.back()->hasPn(nameIn))
{
return;
}
activeFunc->namespaceStack.back()->addPn(nameIn);
activeFunc->namespaceStack[0]->reserveCpp(pnToCpp(nameIn), true);
activeFunc->varDeclareSource+=getTypeCode(typeIn)+" "+pnToCpp(nameIn);
if (!initialValue.empty())
{
activeFunc->varDeclareSource+=" = "+initialValue;
}
activeFunc->varDeclareSource+=";\n";
}
void CppProgram::declareGlobal(const string& nameIn, Type typeIn, string initialValue)
{
if (globalNames->hasPn(nameIn))
return;
string code;
code+=getTypeCode(typeIn);
code+=" ";
globalNames->addPn(nameIn);
code+=globalNames->getCpp(nameIn);
if (!initialValue.empty())
{
code+=" = ";
code+=initialValue;
}
code+=";\n";
globalVarCode+=code;
}
void CppProgram::addHeadCode(const string& code)
{
globalIncludesCode += code + "\n";
}
bool CppProgram::hasFunc(const string& name)
{
return funcs.find(name)!=funcs.end();
}
void CppProgram::addFunc(const string& name, vector<std::pair<string, string>> args, string returnType, string contents)
{
if (hasFunc(name))
{
throw PineconeError("called CppProgram::addFunc with function name '"+name+"', which already exists", INTERNAL_ERROR);
}
globalNames->addPn(name, name);
string cppName=globalNames->getCpp(name);
string prototype;
prototype+=returnType;
prototype+=" "+cppName+"(";
for (int i=0; i<int(args.size()); i++)
{
if (i)
prototype+=", ";
prototype+=args[i].first;
prototype+=" ";
prototype+=args[i].second;
}
prototype+=")";
auto func=CppFunc(new CppFuncBase(prototype, globalNames->makeChild(), (returnType!="" && returnType!="void")));
funcs[name]=func;
func->code(contents);
}
//void CppProgram::pushFunc(const string& name, vector<std::pair<string, string>> args, Type returnType)
void CppProgram::pushFunc(const string& name, const string& cppNameHint, Type leftIn, Type rightIn, Type returnType)
{
if (hasFunc(name))
{
throw PineconeError("called CppProgram::pushFunc with function name '"+name+"', which already exists", INTERNAL_ERROR);
}
globalNames->addPn(name, cppNameHint);
string cppName=globalNames->getCpp(name);
auto funcNames=globalNames->makeChild();
string prototype;
prototype+=getTypeCode(returnType);
prototype+=" "+cppName+"(";
bool keepTuplesTogether=true;
if (keepTuplesTogether)
{
if (leftIn->isCreatable())
{
prototype+=getTypeCode(leftIn)+" me";
funcNames->addPn("me");
}
if (rightIn->isCreatable())
{
if (leftIn->isCreatable())
prototype+=", ";
prototype+=getTypeCode(rightIn)+" in";
funcNames->addPn("in");
}
}
else
{
vector<std::pair<string, string>> args;
if (leftIn->getType()==TypeBase::TUPLE)
{
for (auto i: *leftIn->getAllSubTypes())
{
args.push_back({getTypeCode(i.type), i.name});
}
}
else if (!leftIn->isCreatable())
{
// do nothing
}
else
{
args.push_back({getTypeCode(leftIn), "me"});
}
if (rightIn->getType()==TypeBase::TUPLE)
{
for (auto i: *rightIn->getAllSubTypes())
{
args.push_back({getTypeCode(i.type), i.name});
}
}
else if (!rightIn->isCreatable())
{
// do nothing
}
else
{
args.push_back({getTypeCode(rightIn), "in"});
}
for (int i=0; i<int(args.size()); i++)
{
if (i)
prototype+=", ";
prototype+=args[i].first;
prototype+=" ";
funcNames->addPn(args[i].second, args[i].second);
prototype+=funcNames->getCpp(args[i].second);
}
}
prototype+=")";
activeFunc=CppFunc(new CppFuncBase(prototype, funcNames, returnType->isCreatable()));
funcs[name]=activeFunc;
funcStack.push_back(name);
}
void CppProgram::popFunc()
{
if (activeFunc->getExprLevel()>0 || !activeFunc->getIfFreshLine() || activeFunc->getBlockLevel()>0)
{
throw PineconeError("called CppProgram::popFunc when function wasn't ready", INTERNAL_ERROR);
}
funcStack.pop_back();
if (funcStack.empty())
{
throw PineconeError("called CppProgram::popFunc too many times", INTERNAL_ERROR);
}
activeFunc=funcs[funcStack.back()];
}
string CppProgram::getCppCode()
{
string out;
if (!globalTopCode.empty())
out+=globalTopCode+"\n";
if (!globalIncludesCode.empty())
out+=globalIncludesCode+"\n";
if (!globalTypesCode.empty())
out+=globalTypesCode+"\n";
if (funcs.size()>1)
{
for (auto i: funcs)
{
if (i.first!="main")
out+=i.second->getPrototype()+";\n";
}
out+="\n";
}
if (!globalVarCode.empty())
out+=globalVarCode+"\n";
for (auto i: funcs)
{
out+=i.second->getPrototype();
string funcSrc=i.second->getSource();
if (funcSrc.size()<2)
{
out+="\n{\n\t// empty function\n}\n\n";
}
else
{
if (i.second->getIfReturnsVal() && funcSrc[0]!='{' && searchInString(funcSrc, ";")==int(funcSrc.size())-2)
funcSrc="return "+funcSrc;
out+="\n{\n";
if (!i.second->varDeclareSource.empty())
out+=indentString(i.second->varDeclareSource+"\n", indent);
out+=indentString(funcSrc, indent);
if (!out.empty() && out.back()!='\n')
out+=";\n";
//if (i.first=="main")
// out+=indentString("return 0;\n", indent);
//if (out.substr(out.size()-2, 2)!=";\n")
// out+=";\n";
out+="}\n\n";
}
}
out+=
"int main(int argcIn, char** argvIn)\n\
{\n\
argc = argcIn;\n\
argv = argvIn;\n\
if (argc >= 2 && strcmp(argv[1], \"--running-from-pinecone\") == 0)\n\
{\n\
argc -= 2;\n\
if (argc == 0)\n\
argv = 0;\n\
else\n\
argv += 2;\n\
}\n\
_main();\n\
return 0;\n\
}\n";
return out;
}
================================================
FILE: src/ErrorHandler.cpp
================================================
#include "../h/ErrorHandler.h"
#include "../h/msclStringFuncs.h"
#include "../h/SourceFile.h"
#include <iostream>
using std::cout;
using std::endl;
ErrorHandler error;
string ErrorHandler::priorityToStr(ErrorPriority in)
{
switch (in)
{
case SOURCE_ERROR:
return "error";
break;
case SOURCE_WARNING:
return "warning";
break;
case JSYK:
return "jsyk";
break;
case INTERNAL_ERROR:
return "INTERNAL ERROR";
break;
case RUNTIME_ERROR:
return "runtime error";
break;
default:
return "UNKNOWN PRIORITY LEVEL";
break;
}
}
void ErrorHandler::log(string msg, ErrorPriority priority, Token token)
{
if (priority==SOURCE_ERROR || priority==INTERNAL_ERROR || priority==RUNTIME_ERROR)
errorHasBeenLogged=true;
// gcc style
//if (token)
// cout << token->getFile() << ":" << token->getLine() << ":" << token->getCharPos() << ": ";
//cout << priorityToStr(priority) << ": " << msg << endl;
// Pinecone style
cout << priorityToStr(priority);
if (token)
{
cout << " in '" << token->getFile()->getFilename() << "' on line " << token->getLine() << ":" << endl;
cout << indentString(msg, " ") << endl;
string line=token->getFile()->getLine(token->getLine());
int wspace=0;
for (; wspace<int(line.size()) && (line[wspace]==' ' || line[wspace]=='\t' || line[wspace]=='\n'); wspace++) {}
string arrows="";
for (int i=0; i<token->getCharPos()-1-wspace; i++)
arrows+=" ";
for (int i=0; i<int(token->getText().size()); i++)
arrows+="^";
cout << indentString(""+line.substr(wspace, string::npos)+"\n"+arrows, " ") << endl;
}
else
{
cout << ": " << msg << endl;
}
}
void ErrorHandler::msg(string in)
{
cout << "message: " << in << endl;
}
PineconeError::PineconeError(string msgIn, ErrorPriority priorityIn, Token tokenIn)
{
msg=msgIn;
priority=priorityIn;
token=tokenIn;
}
void PineconeError::log()
{
error.log(msg, priority, token);
}
================================================
FILE: src/Lexer.cpp
================================================
#include "../h/Token.h"
#include "../h/ErrorHandler.h"
#include "../h/Operator.h"
#include "../h/AllOperators.h"
#include "../h/SourceFile.h"
#include <vector>
using std::vector;
#include <unordered_map>
using std::unordered_map;
class CharClassifier
{
public:
enum Type
{
WHITESPACE,
LINE_BREAK,
NEWLINE,
LETTER,
DIGIT,
OPERATOR,
STRING_QUOTE,
SINGLE_LINE_COMMENT,
MULTI_LINE_COMMENT_START,
MULTI_LINE_COMMENT_END,
UNKNOWN,
};
static inline TokenData::Type getTokenType(CharClassifier::Type type, TokenData::Type previousType);
inline CharClassifier::Type get(shared_ptr<SourceFile> file, int i);
private:
void setUp();
private:
unordered_map<char, CharClassifier::Type> hm;
bool hasSetUp=false;
};
CharClassifier charClassifier;
void CharClassifier::setUp()
{
hm[' ']=WHITESPACE;
hm['\t']=WHITESPACE;
hm['\r']=WHITESPACE; // ignore '\r' character on windows style line ending
hm['\n']=NEWLINE;
hm[';']=LINE_BREAK;
for (char c='a'; c<='z'; ++c)
hm[c]=LETTER;
for (char c='A'; c<='Z'; ++c)
hm[c]=LETTER;
hm['_']=LETTER;
for (char c='0'; c<='9'; ++c)
hm[c]=DIGIT;
hm['#']=SINGLE_LINE_COMMENT;
hm['"']=STRING_QUOTE;
unordered_map<string, Operator>& opsMap=ops->getOpsMap();
for (auto i=opsMap.begin(); i!=opsMap.end(); ++i)
{
string str=(*i).first;
for (unsigned j=0; j<str.size(); j++)
{
hm[str[j]]=OPERATOR;
}
}
hasSetUp=true;
}
inline CharClassifier::Type CharClassifier::get(shared_ptr<SourceFile> file, int index)
{
// set up the first time this function is called
if (!hasSetUp)
setUp();
// chack fo multi line comments in a special way, because they are multi character
switch ((*file)[index])
{
case '/':
if (index<int(file->size())-1 && (*file)[index+1]=='/')
return MULTI_LINE_COMMENT_START;
break;
case '\\':
if (index>0 && (*file)[index-1]=='\\')
return MULTI_LINE_COMMENT_END;
break;
case '.': // allow a . to be a digit character only if it is followed by a digit
if (index<int(file->size())-1)
{
auto i=hm.find((*file)[index+1]);
if (i!=hm.end() && i->second==DIGIT)
return DIGIT;
}
break;
}
// handle all other cases using the hashmap
char c=(*file)[index];
auto i=hm.find(c);
if (i==hm.end())
return UNKNOWN;
else
return i->second;
}
inline TokenData::Type CharClassifier::getTokenType(CharClassifier::Type type, TokenData::Type previousType)
{
if (previousType==TokenData::LINE_COMMENT)
{
if (type==NEWLINE)
return TokenData::WHITESPACE;
else
return TokenData::LINE_COMMENT;
}
else if (previousType==TokenData::BLOCK_COMMENT)
{
if (type==MULTI_LINE_COMMENT_END)
return TokenData::WHITESPACE;
else
return TokenData::BLOCK_COMMENT;
}
else if (previousType==TokenData::STRING_LITERAL)
{
if (type==STRING_QUOTE)
return TokenData::WHITESPACE;
else
return TokenData::STRING_LITERAL;
}
switch (type)
{
case SINGLE_LINE_COMMENT:
return TokenData::LINE_COMMENT;
case MULTI_LINE_COMMENT_START:
return TokenData::BLOCK_COMMENT;
case MULTI_LINE_COMMENT_END:
error.log("block comment end without start", SOURCE_ERROR);
return TokenData::UNKNOWN;
case WHITESPACE:
return TokenData::WHITESPACE;
case LINE_BREAK:
case NEWLINE:
return TokenData::LINE_END;
case OPERATOR:
return TokenData::OPERATOR;
case LETTER:
case DIGIT:
if (previousType==TokenData::IDENTIFIER || previousType==TokenData::LITERAL)
return previousType;
else if (type==DIGIT)
return TokenData::LITERAL;
else
return TokenData::IDENTIFIER;
case STRING_QUOTE:
return TokenData::STRING_LITERAL;
default:
return TokenData::UNKNOWN;
}
}
void lexString(shared_ptr<SourceFile> file, vector<Token>& tokens)
{
string tokenTxt;
int line=1;
int charPos=1;
TokenData::Type type=TokenData::WHITESPACE;
for (int i=0; i<file->size(); i++)
{
CharClassifier::Type charType=charClassifier.get(file, i);
TokenData::Type newType=CharClassifier::getTokenType(charType, type);
if (newType!=type)
{
if (!tokenTxt.empty())
{
if (type==TokenData::OPERATOR)
{
vector<Operator> opMatches;
ops->get(tokenTxt, opMatches);
for (auto op: opMatches)
{
tokens.push_back(makeToken(op->getText(), file, line, charPos-tokenTxt.size(), type, op));
}
}
else if (type==TokenData::LINE_COMMENT || type==TokenData::BLOCK_COMMENT)
{
// do nothing
}
else
{
Token token=makeToken(tokenTxt, file, line, charPos-tokenTxt.size(), type);
if (type==TokenData::UNKNOWN)
{
PineconeError("invalid token '"+tokenTxt+"'", SOURCE_ERROR, token).log();
}
else
{
tokens.push_back(token);
}
}
}
tokenTxt="";
}
if (newType!=TokenData::WHITESPACE && newType!=TokenData::LINE_END)
{
if (newType==TokenData::STRING_LITERAL && (*file)[i]=='\\')
{
i++;
if ((*file)[i]=='n')
tokenTxt+='\n';
else if ((*file)[i]=='"')
tokenTxt+='"';
else if ((*file)[i]=='t')
tokenTxt+='\t';
else if ((*file)[i]=='\\')
tokenTxt+='\\';
else
throw PineconeError(string()+"invalid escape character '\\"+(*file)[i]+"'", SOURCE_ERROR, makeToken(tokenTxt+(*file)[i], file, line, charPos-tokenTxt.size(), type));
}
else
{
tokenTxt+=(*file)[i];
}
}
type=newType;
if ((*file)[i]=='\n')
{
line++;
charPos=1;
}
else
{
charPos++;
}
}
}
================================================
FILE: src/Namespace.cpp
================================================
#include "../h/Namespace.h"
#include "../h/StackFrame.h"
#include "../h/msclStringFuncs.h"
#include "../h/ErrorHandler.h"
#include "../h/utils/stringNumConversion.h"
void NamespaceData::IdMap::add(string key, AstNode node)
{
auto i=nodes.find(key);
if (i==nodes.end())
{
nodes[key]=vector<AstNode>();
}
nodes[key].push_back(move(node));
}
void NamespaceData::IdMap::get(string key, vector<AstNodeBase*>& out)
{
auto matches=nodes.find(key);
if (matches!=nodes.end())
{
for (unsigned i=0; i<matches->second.size(); i++)
{
out.push_back(&*matches->second[i]);
}
}
}
Namespace NamespaceData::makeRootNamespace()
{
return Namespace(new NamespaceData(Namespace(nullptr), shared_ptr<StackFrame>(new StackFrame()), "root"));
}
Namespace NamespaceData::makeChild()
{
return Namespace(new NamespaceData(shared_from_this(), stackFrame));
}
Namespace NamespaceData::makeChildAndFrame(string nameIn)
{
return Namespace(new NamespaceData(shared_from_this(), shared_ptr<StackFrame>(new StackFrame()), nameIn));
}
NamespaceData::NamespaceData(Namespace parentIn, shared_ptr<StackFrame> stackFrameIn, string nameIn)
{
parent=parentIn;
stackFrame=stackFrameIn;
myName=nameIn;
}
string NamespaceData::getString()
{
/*string out;
out+="normal functions:\n";
for (auto i: actions)
{
out+="\t";
out+=i.first;
if (i.second.size()>1)
out+=" (" + to_string(i.second.size()) + " overloads)";
out+="\n";
}
out+="\nconverters:\n";
for (auto i: converters)
{
out+="\t";
out+=i.first->getString();
if (i.second.size()>1)
out+=" (" + to_string(i.second.size()) + " overloads)";
out+="\n";
}
out+="\noperators:\n";
for (auto i: operators)
{
out+="\t";
out+=i.first->getText();
if (i.second.size()>1)
out+=" (" + to_string(i.second.size()) + " overloads)";
out+="\n";
}
out+="\ntypes:\n";
for (auto i: types)
{
out+="\t";
out+=i.second->getString() + " (" + i.second->getString() + ")";
out+="\n";
}
return out;*/
return "NamespaceData::getString not yet implemented";
}
string NamespaceData::getStringWithParents()
{
auto ptr=shared_from_this();
string out;
while (ptr)
{
out=putStringInBox(ptr->getString()+"\n"+out, ptr->myName);
ptr=ptr->parent;
}
return out;
}
void NamespaceData::setInput(Type left, Type right)
{
if (parent && parent->getStackFrame()==stackFrame)
{
error.log("called "+FUNC+" on namespace that is not the root of a stack frame, thus it can not get input", INTERNAL_ERROR);
return;
}
stackFrame->setInput(left, right);
//if (!left->isVoid())
if (left->isCreatable())
{
string leftName="me";
size_t leftOffset=stackFrame->getLeftOffset();
Action leftGetAction=varGetAction(leftOffset, left, leftName);
Action leftSetAction=varSetAction(leftOffset, left, leftName);
addNode(AstActionWrapper::make(leftGetAction), leftName);
addNode(AstActionWrapper::make(leftSetAction), leftName);
}
//if (!right->isVoid())
if (right->isCreatable())
{
string rightName="in";
size_t rightOffset=stackFrame->getRightOffset();
Action rightGetAction=varGetAction(rightOffset, right, rightName);
Action rightSetAction=varSetAction(rightOffset, right, rightName);
addNode(AstActionWrapper::make(rightGetAction), rightName);
addNode(AstActionWrapper::make(rightSetAction), rightName);
}
}
Action NamespaceData::addVar(Type type, string name)
{
size_t offset=stackFrame->getSize();
stackFrame->addMember(type);
Action getAction;
Action setAction;
Action copyAction;
Namespace top=shared_from_this();
while(top->parent)
{
top=top->parent;
}
if (stackFrame!=top->stackFrame)
{
getAction=varGetAction(offset, type, name);
setAction=varSetAction(offset, type, name);
}
else
{
getAction=globalGetAction(offset, type, name);
setAction=globalSetAction(offset, type, name);
}
copyAction=getCopier(type);
if (copyAction)
{
dynamicActions.add(name, AstActionWrapper::make(branchAction(voidAction, copyAction, getAction)));
}
else
{
dynamicActions.add(name, AstActionWrapper::make(getAction));
}
dynamicActions.add(name, AstActionWrapper::make(setAction));
Action destructor=getDestroyer(type);
if (destructor)
{
destructorActions.push_back(branchAction(voidAction, destructor, getAction));
}
return setAction;
}
void NamespaceData::addNode(AstNode node, string id)
{
if (node->nameHint.empty())
{
node->nameHint=id;
node->nameHintSet();
}
if (node->isType())
{
types.add(id, move(node));
}
/*
else if (id=="__destroy__")
{
Action action=node->getAction();
if (action->getInRightType()->isVoid() || !action->getInLeftType()->isVoid() || !action->getReturnType()->isVoid())
{
throw PineconeError("incorrect type signiture for destroyer", SOURCE_ERROR, node->getToken());
}
destructors.add(str::ptrToUniqueStr(&*action->getInRightType(), 6), move(node));
}
else if (id=="__copy__")
{
Action action=node->getAction();
if (action->getInRightType()->isVoid() || !action->getInLeftType()->isVoid() || action->getReturnType()!=action->getInRightType())
{
throw PineconeError("incorrect type signiture for copier", SOURCE_ERROR, node->getToken());
}
copiers.add(str::ptrToUniqueStr(&*action->getReturnType(), 6), move(node));
}
*/
else
{
// if the left or the right is a Whatev and the types match up
if (node->canBeWhatev())
{
whatevActions.add(id, move(node));
}
else
{
actions.add(id, move(node));
}
}
}
Type NamespaceData::getType(string name, bool throwSourceError, Token tokenForError)
{
vector<AstNodeBase*> results;
types.get(name, results);
if (results.empty())
{
if (parent)
return parent->getType(name, throwSourceError, tokenForError);
else if (throwSourceError)
throw PineconeError("'"+name+"' type not found", SOURCE_ERROR);
else
return nullptr;
}
else if (results.size()!=1)
{
throw PineconeError("namespace has multiple defenitions of the same type '"+name+"'", INTERNAL_ERROR);
}
else if (results[0]->getReturnType()->getType()!=TypeBase::METATYPE)
{
throw PineconeError("node returning non meta type stored in namespace type map for type '"+name+"'", INTERNAL_ERROR);
}
else
{
return results[0]->getReturnType()->getSubType();
}
}
Action NamespaceData::getDestroyer(Type type)
{
return getActionForTokenWithInput(makeToken("__destroy__"), Void, type, false, false, nullptr);
/*
vector<AstNodeBase*> nodes;
destructors.get(str::ptrToUniqueStr(&*type, 6), nodes);
if (nodes.empty())
{
if (parent)
return parent->getDestroyer(type);
else
return nullptr;
}
else if (nodes.size()>1)
{
throw PineconeError("multiple destroyers for a single type in a single namespace", INTERNAL_ERROR);
}
else
{
return nodes[0]->getAction();
}
*/
}
Action NamespaceData::wrapInDestroyer(Action in)
{
Action destroyer=getDestroyer(in->getReturnType());
return destroyer ?
branchAction(voidAction, destroyer, in)
:
in
;
}
Action NamespaceData::getCopier(Type type)
{
return getActionForTokenWithInput(makeToken("__copy__"), Void, type, false, false, nullptr);
/*
vector<AstNodeBase*> nodes;
copiers.get(str::ptrToUniqueStr(&*type, 6), nodes);
if (nodes.empty())
{
if (parent)
return parent->getCopier(type);
else
return nullptr;
}
else if (nodes.size()>1)
{
throw PineconeError("multiple copiers for a single type in a single namespace", INTERNAL_ERROR);
}
else
{
return nodes[0]->getAction();
}
*/
}
Action NamespaceData::getActionForTokenWithInput(Token token, Type left, Type right, bool dynamic, bool throwSourceError, Token tokenForError)
{
vector<Action> matches;
vector<AstNodeBase*> nodes;
bool foundNodes=false;
AstNode tupleNode; // this is needed for memory management, so if a tuple node is needed it can be kept around until the function exits
string searchText = (token->getOp() ? token->getOp()->getText() : token->getText());
getNodes(nodes, searchText, true, dynamic, false);
if (left->getType()==TypeBase::TUPLE && token->getType()==TokenData::IDENTIFIER)
{
auto match=left->getSubType(searchText);
if (match.type)
{
if (right->isVoid())
{
tupleNode=AstActionWrapper::make(getElemFromTupleAction(left, searchText));
nodes.push_back(&*tupleNode);
}
}
}
if (!nodes.empty())
foundNodes=true;
nodesToMatchingActions(matches, nodes, left, right);
if (!matches.empty())
{
if (matches.size() == 1)
{
return matches[0];
}
else if (throwSourceError)
{
throw PineconeError("multiple matching instances of '"+token->getText()+"' found", SOURCE_ERROR, tokenForError);
}
else
{
return nullptr;
}
}
nodes.clear();
getNodes(nodes, searchText, false, false, true);
if (!nodes.empty())
foundNodes=true;
for (auto i: nodes)
{
AstNode instance=i->makeCopyWithSpecificTypes(left, right);
if (instance)
{
matches.push_back(instance->getAction());
actions.add(token->getText(), move(instance));
}
}
if (!matches.empty())
{
if (matches.size() == 1)
{
return matches[0];
}
else if (throwSourceError)
{
throw PineconeError("multiple whatev instances of '"+token->getText()+"' found", SOURCE_ERROR, tokenForError);
}
else
{
return nullptr;
}
}
if (!foundNodes && dynamic && token->getType()==TokenData::IDENTIFIER && left->isVoid() && right->isCreatable())
{
return addVar(right, token->getText());
}
if (throwSourceError)
{
if (foundNodes)
throw PineconeError("correct overload of '"+token->getText()+"' not found for types "+left->getString()+" and "+right->getString(), SOURCE_ERROR, tokenForError);
else
throw PineconeError("'"+token->getText()+"' not found", SOURCE_ERROR, tokenForError);
}
else
{
return nullptr;
}
}
void NamespaceData::getNodes(vector<AstNodeBase*>& out, string text, bool checkActions, bool checkDynamic, bool checkWhatev)
{
if (checkActions)
{
actions.get(text, out);
}
if (checkDynamic)
{
dynamicActions.get(text, out);
}
if (checkWhatev)
{
whatevActions.get(text, out);
}
if (parent)
parent->getNodes(out, text, checkActions, checkDynamic, checkWhatev);
}
void NamespaceData::nodesToMatchingActions(vector<Action>& out, vector<AstNodeBase*>& nodes, Type leftInType, Type rightInType)
{
for (auto i: nodes)
{
Action action=i->getAction();
if (action->getInLeftType()->matches(leftInType) && action->getInRightType()->matches(rightInType))
out.push_back(action);
//Action converter=getConverter(action, leftInType, rightInType);
}
}
================================================
FILE: src/Parser.cpp
================================================
#include "../h/Token.h"
#include "../h/AstNode.h"
#include "../h/Namespace.h"
#include "../h/ErrorHandler.h"
#include "../h/StackFrame.h"
#include "../h/AllOperators.h"
#include "../h/msclStringFuncs.h"
#include "../h/AstNode.h"
#include <vector>
using std::vector;
#include <iostream>
using std::cout;
using std::endl;
using std::min;
using std::max;
using std::pair;
void lexString(shared_ptr<SourceFile> file, vector<Token>& tokens);
// unless otherwise noted, these are what the perams for the following functions mean
// tokens: the tokens to parse
// table: the table to use
// left: left most token to parse (inclusive)
// right: right most token to parse (inclusive)
// returns: (if type is AstNode) the action pointer for that section of the program
// splits a stream of tokens into a ListAstNode and calls parseExpression on each expression
void parseTokenList(const vector<Token>& tokens, int left, int right, vector<AstNode>& nodes);
int findExpressionSplit(const vector<Token>& tokens, int left, int right);
// recursivly parses a single expression (no action lists)
AstNode parseExpression(const vector<Token>& tokens, int left, int right);
// returns the index of the closing brace that matches the given opening brace index, works with (), [], and {}
// tokens: the token array to use
// start: the index of an open peren
// returns: the index of the close peren that matches
int skipBrace(const vector<Token>& tokens, int start);
void parseSequence(const vector<Token>& tokens, int left, int right, Operator splitter, vector<AstNode>& out);
AstNode parseOperator(const vector<Token>& tokens, int left, int right, int index);
//AstNode parseLiteral(Token token);
unique_ptr<AstType> parseType(const vector<Token>& tokens, int left, int right);
//AstNode parseSingleTypeElement(const vector<Token>& tokens, int& i, int right, string& name, Type& type);
//Type parseTypeToken(Token token);
void importFile(vector<AstNode>& nodes, string path);
//AstNode parseIdentifier(Token token, AstNode leftIn, AstNode rightIn);
//void parseIdentifierConst(Token token, AstNode rightIn);
AstNode astNodeFromTokens(const vector<Token>& tokens, int left, int right)
{
vector<AstNode> nodes;
parseTokenList(tokens, left, right, nodes);
if (nodes.size()==0)
{
return AstVoid::make();
}
else if (nodes.size()==1)
{
return move(nodes[0]);
}
else
{
return AstList::make(nodes);
}
}
int skipBrace(const vector<Token>& tokens, int start)
{
Operator open, close;
int step;
Operator op=tokens[start]->getOp();
if (tokens[start]->getOp()==ops->openPeren)
{
open=ops->openPeren;
close=ops->closePeren;
step=1;
}
else if (tokens[start]->getOp()==ops->closePeren)
{
open=ops->closePeren;
close=ops->openPeren;
step=-1;
}
else if (tokens[start]->getOp()==ops->openSqBrac)
{
open=ops->openSqBrac;
close=ops->closeSqBrac;
step=1;
}
else if (tokens[start]->getOp()==ops->closeSqBrac)
{
open=ops->closeSqBrac;
close=ops->openSqBrac;
step=-1;
}
else if (tokens[start]->getOp()==ops->openCrBrac)
{
open=ops->openCrBrac;
close=ops->closeCrBrac;
step=1;
}
else if (tokens[start]->getOp()==ops->closeCrBrac)
{
open=ops->closeCrBrac;
close=ops->openCrBrac;
step=-1;
}
else
{
throw PineconeError(FUNC + " called with index that is not a valid brace", INTERNAL_ERROR, tokens[start]);
}
int c=1;
int i=start;
while(true)
{
i+=step;
if (i>=int(tokens.size()))
{
throw PineconeError("no matching brace", SOURCE_ERROR, tokens[start]);
}
if (tokens[i]->getOp()==open)
{
c++;
}
else if (tokens[i]->getOp()==close)
{
c--;
if (c<=0)
{
return i;
}
}
}
}
/*AstNode parseExpression(const vector<Token>& tokens, int left, int right)
{
//error.log("parsing expression: "+stringFromTokens(tokens, left, right), JSYK);
if (left>right)
{
throw PineconeError(FUNC + " sent left higher then right", INTERNAL_ERROR, tokens[left]);
}
else if (left==right)
{
return AstToken::make(tokens[left]);
}
vector<bool> isMinLeft(right-left+1);
vector<bool> isMinRight(right-left+1);
int lowest;
lowest=10000; //an number bigger then any precedence
for (int i=left; i<=right; i++)
{
isMinLeft[i]=false;
isMinRight[i]=false;
}
for (int i=left; i<=right; i++)
{
Operator op=tokens[i]->getOp();
if (op)
{
if (op==ops->openPeren || op==ops->openSqBrac || op==ops->openCrBrac)
{
int j=i;
i=skipBrace(tokens, i);
if (j==left && i==right)
{
if (op==ops->openPeren)
{
if (left+1<right)
return parseTokenList(tokens, left+1, right-1);
else
return AstVoid::make(); // a rare place where a astVoid may actually be intended by the programmer
}
else if (op==ops->openCrBrac)
{
return parseType(tokens, left+1, right-1);
}
else
{
throw PineconeError("unknown bracket '"+op->getText()+"'", INTERNAL_ERROR);
}
}
}
else
{
if (op->getLeftPrece()<lowest)
{
isMinLeft[i]=true;
}
}
lowest=min(lowest, op->getRightPrece());
}
}
lowest=10000; //an number bigger then any precedence
for (int i=right; i>=left; i--)
{
Operator op=tokens[i]->getOp();
if (op)
{
if (op==ops->closePeren || op==ops->closeSqBrac || op==ops->closeCrBrac)
{
i=skipBrace(tokens, i);
}
else
{
if (op->getRightPrece()<lowest)
{
isMinRight[i]=true;
}
lowest=min(lowest, op->getLeftPrece());
}
}
}
for (int i=left; i<=right; i++)
{
if (isMinLeft[i] && isMinRight[i])
{
AstNode leftNode=parseExpression(tokens, left, i-1);
AstNode rightNode=parseExpression(tokens, i+1, right);
if (tokens[i]->getOp()==ops->colon || tokens[i]->getOp()==ops->doubleColon)
{
return AstExpression::make(AstVoid::make(), move(leftNode), move(rightNode));
}
else
{
return AstExpression::make(move(leftNode), AstToken::make(tokens[i]), move(rightNode));
}
}
}
throw PineconeError("could not find where to split expression '" + stringFromTokens(tokens, left, right) + "'", SOURCE_ERROR, tokens[left]);
//error.log("range: " + ([&]()->string{string out; for (int i=left; i<=right; i++) {out+=tokens[i]->getText()+" ";} return out;})(), JSYK, tokens[left]);
//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]);
}
*/
int findExpressionSplit(const vector<Token>& tokens, int left, int right)
{
int minPrece=-1;
int indexOfMin=-1;
for (int i=left; i<=right; i++)
{
//cout << "looking at " << tokens[i]->getText() << endl;
/*if (tokens[i]->getOp())
{
//cout << "precedence: " << tokens[i]->getOp()->getPrecedence()
}
*/
if (ops->isOpenBrac(tokens[i]->getOp()))
{
int j=skipBrace(tokens, i);
i=j; // i is now the close brace, and after it is incremented it will be the token after that
}
else if (tokens[i]->getOp() && (minPrece<0 || tokens[i]->getOp()->getPrecedence()<minPrece))
{
minPrece=tokens[i]->getOp()->getPrecedence();
indexOfMin=i;
// this ensures that if the precedence is divisable by 2, the same precedence again will replace this one as the min
// it is my way of making even precedences be right associative and odd ones be left associative
if (minPrece%2)
{
minPrece++;
}
}
}
if (indexOfMin<0)
{
throw PineconeError(FUNC+" could not find operator to split expression", INTERNAL_ERROR, tokens[left]);
}
return indexOfMin;
}
AstNode parseExpression(const vector<Token>& tokens, int left, int right)
{
//error.log(FUNC+" called on '"+stringFromTokens(tokens, left, right)+"'", JSYK);
if (left>right)
{
throw PineconeError(FUNC + " sent left higher then right", INTERNAL_ERROR, tokens[left]);
}
else if (left==right)
{
return AstToken::make(tokens[left]);
}
if (ops->isOpenBrac(tokens[left]->getOp()) && skipBrace(tokens, left)==right) // if the braces enclose this entire expression
{
if (tokens[left]->getOp()==ops->openPeren)
{
return astNodeFromTokens(tokens, left+1, right-1);
}
else if (tokens[left]->getOp()==ops->openCrBrac)
{
return parseType(tokens, left+1, right-1);
}
else
{
throw PineconeError("unhandled brace '"+tokens[left]->getOp()->getText()+"'", INTERNAL_ERROR, tokens[left]);
}
}
int i=findExpressionSplit(tokens, left, right);
Operator op=tokens[i]->getOp();
if (op==ops->minus && i==left && i!=right)
{
//dont error
}
else if ((i==left)==op->takesLeftInput() || (i==right)==op->takesRightInput())
{
throw PineconeError("improper use of '"+op->getText()+"' operator", SOURCE_ERROR, tokens[i]);
}
if (op==ops->pipe)
{
throw PineconeError("invalid use of '"+op->getText()+"'", SOURCE_ERROR, tokens[i]);
}
else if (op==ops->ifOp || op==ops->loop || op==ops->rightArrow || op==ops->andOp || op==ops->orOp)
{
vector<AstNode> leftNodes;
vector<AstNode> rightNodes;
if (i>left)
parseSequence(tokens, left, i-1, ops->pipe, leftNodes);
if (i<right)
parseSequence(tokens, i+1, right, ops->pipe, rightNodes);
return AstOpWithInput::make(leftNodes, tokens[i], rightNodes);
}
else if (op==ops->comma)
{
vector<AstNode> nodes;
parseSequence(tokens, left, right, ops->comma, nodes);
return AstTuple::make(nodes);
}
else if (op==ops->doubleColon)
{
unique_ptr<AstToken> centerNode=nullptr;
AstNode rightNode=nullptr;
if (i==left+1 && tokens[i-1]->getType()==TokenData::IDENTIFIER)
{
centerNode=AstToken::make(tokens[i-1]);
}
else
{
throw PineconeError("you can only use constant assignment on a single identifier", SOURCE_ERROR, tokens[i]);
}
if (i<right)
{
rightNode=parseExpression(tokens, i+1, right);
}
else
{
rightNode=AstVoid::make();
}
return AstConstExpression::make(move(centerNode), move(rightNode));
}
else if (op==ops->notEqual)
{
AstNode rightNode=i<right?parseExpression(tokens, i+1, right):AstVoid::make();
AstNode leftNode=i>left?parseExpression(tokens, left, i-1):AstVoid::make();
AstNode centerNode=AstToken::make(
makeToken(
ops->equal->getText(),
tokens[i]->getFile(),
tokens[i]->getLine(),
tokens[i]->getCharPos()+1,
TokenData::OPERATOR,
ops->equal
)
);
AstNode notNode=AstToken::make(
makeToken(
ops->notOp->getText(),
tokens[i]->getFile(),
tokens[i]->getLine(),
tokens[i]->getCharPos(),
TokenData::OPERATOR,
ops->notOp
)
);
return AstExpression::make(
AstVoid::make(),
move(notNode),
AstExpression::make(
move(leftNode),
move(centerNode),
move(rightNode)
)
);
}
else if (op==ops->plusPlus || op==ops->minusMinus)
{
throw PineconeError("++ and -- are not yet implemented", SOURCE_ERROR, tokens[i]);
//AstNode leftNode=parseExpression(tokens, left, i-1);
//return AstExpression::make(AstVoid::make(), leftNode, AstExpression::make(leftNode, AstToken::make(Token)))
}
else if (op==ops->dot)
{
return AstExpression::make
(
i>left ? parseExpression(tokens, left, i-1) : AstVoid::make(),
i<right ? parseExpression(tokens, i+1, right) : AstVoid::make(),
AstVoid::make()
);
}
else if (op==ops->colon)
{
AstNode leftNode=AstVoid::make();
AstNode centerNode=parseExpression(tokens, left, i-1);;
AstNode rightNode=i<right?parseExpression(tokens, i+1, right):AstVoid::make();
// make sure if it is an abc.xyz: ijk structure, it gets parsed as such, rather then (abc.xyz): ijk
// we do this by parsing it the latter way (already done) and then detecting if we need to change it
if (typeid(*centerNode)==typeid(AstExpression))
{
AstExpression * exprNode=(AstExpression*)&*centerNode;
if (!exprNode->leftIn->isVoid() && !exprNode->center->isVoid() && exprNode->rightIn->isV
gitextract_dt6obtpb/
├── .gitignore
├── LICENSE
├── Makefile
├── _config.yml
├── changelog.md
├── codeblocks/
│ ├── Pinecone.cbp
│ └── readme.md
├── examples/
│ ├── brainfuck.pn
│ ├── fizzBuzz.pn
│ ├── hello_world.pn
│ ├── historical/
│ │ └── snake_original.pn
│ ├── incomplete/
│ │ └── hashmap.pn
│ ├── morse.pn
│ ├── queue.pn
│ ├── readme.md
│ ├── simple_demo.pn
│ └── snake_new.pn
├── h/
│ ├── Action.h
│ ├── AllOperators.h
│ ├── AstNode.h
│ ├── CppProgram.h
│ ├── ErrorHandler.h
│ ├── Namespace.h
│ ├── Operator.h
│ ├── PineconeProgram.h
│ ├── SourceFile.h
│ ├── StackFrame.h
│ ├── Token.h
│ ├── Type.h
│ ├── VERSION.h
│ ├── msclStringFuncs.h
│ └── utils/
│ ├── fileUtils.h
│ ├── stringArray.h
│ ├── stringDrawing.h
│ ├── stringNumConversion.h
│ └── stringUtils.h
├── other/
│ ├── pinecone.pn
│ ├── pinecone_concept.txt
│ ├── readme.md
│ └── user_testing.txt
├── readme.md
├── repl/
│ ├── readme.md
│ └── repl.sh
├── src/
│ ├── Actions/
│ │ ├── Action.cpp
│ │ ├── BoolOpAction.cpp
│ │ ├── BranchAction.cpp
│ │ ├── FunctionAction.cpp
│ │ ├── IfAction.cpp
│ │ ├── ListAction.cpp
│ │ ├── LoopAction.cpp
│ │ ├── MakeTupleAction.cpp
│ │ ├── TypeAction.cpp
│ │ └── VarAction.cpp
│ ├── AllOperators.cpp
│ ├── AstNode.cpp
│ ├── CppProgram.cpp
│ ├── ErrorHandler.cpp
│ ├── Lexer.cpp
│ ├── Namespace.cpp
│ ├── Parser.cpp
│ ├── PineconeProgram.cpp
│ ├── PineconeStdLib.cpp
│ ├── ResolveLiteral.cpp
│ ├── SourceFile.cpp
│ ├── StackFrame.cpp
│ ├── Token.cpp
│ ├── Type.cpp
│ ├── main.cpp
│ ├── msclStringFuncs.cpp
│ └── utils/
│ ├── fileUtils.cpp
│ ├── stringArray.cpp
│ ├── stringDrawing.cpp
│ ├── stringNumConversion.cpp
│ └── stringUtils.cpp
├── tests/
│ ├── integration/
│ │ ├── brainfuck.pn
│ │ ├── morse.pn
│ │ └── queue.pn
│ ├── readme.md
│ ├── regression/
│ │ ├── bool_short_circuit.pn
│ │ ├── cpp_bad_escape_seq.pn
│ │ ├── cpp_global_and_local_same_name.pn
│ │ ├── error_on_nonexistant_file.pn
│ │ ├── function_with_one_named_arg.pn
│ │ ├── if_as_ternary.pn
│ │ ├── multiple_left_inputs.pn
│ │ ├── negative_literal.pn
│ │ └── no_newline_at_end.pn
│ ├── run_tests.pn
│ ├── unfixed/
│ │ └── backslash_in_block_comment.pn
│ └── unit/
│ ├── conditionals.pn
│ ├── constants.pn
│ ├── destroyers_and_copiers.pn
│ ├── funcs.pn
│ ├── generate_windows_line_endings.sh
│ ├── loops.pn
│ ├── operators.pn
│ ├── order_of_ops.pn
│ ├── strings.pn
│ ├── type_info.pn
│ ├── vars.pn
│ ├── whatevs.pn
│ └── windows_line_endings.pn
└── tutorials/
├── 0_setting_up.md
├── 1_basic_concepts.md
├── 2_control_flow.md
├── 3_strings_and_input.md
├── 4_structures_and_functions.md
├── 5_whatevs.md
├── 6_transpiling_to_cpp.md
├── 7_temporary_hacks.md
└── index.md
SYMBOL INDEX (375 symbols across 46 files)
FILE: h/Action.h
function class (line 25) | class ActionData
type shared_ptr (line 69) | typedef shared_ptr<ActionData> Action;
FILE: h/AllOperators.h
function class (line 11) | class AllOperators
FILE: h/AstNode.h
type shared_ptr (line 8) | typedef shared_ptr<NamespaceData> Namespace;
type unique_ptr (line 14) | typedef unique_ptr<AstNodeBase> AstNode;
function class (line 18) | class AstNodeBase
function class (line 144) | class AstVoid: public AstNodeBase
function class (line 177) | class AstList: public AstNodeBase
function class (line 216) | class AstToken: public AstNodeBase
function class (line 248) | class AstFuncBody: public AstNodeBase
function AstNode (line 271) | AstNode makeCopy(bool copyCache)
function Token (line 287) | Token getToken() {return bodyNode->getToken();}
function setTypesInput (line 289) | void setTypesInput()
function canBeWhatev (line 300) | bool canBeWhatev()
function class (line 315) | class AstExpression: public AstNodeBase
function class (line 351) | class AstConstExpression: public AstNodeBase
function class (line 389) | class AstOpWithInput: public AstNodeBase
function class (line 431) | class AstTuple: public AstNodeBase
function class (line 467) | class AstType: public AstNodeBase
function class (line 478) | class AstTypeType: public AstType
function class (line 520) | class AstVoidType: public AstType
FILE: h/CppProgram.h
function class (line 22) | class CppNameContainer
function class (line 48) | class CppFuncBase
type shared_ptr (line 88) | typedef shared_ptr<CppFuncBase> CppFunc;
function class (line 90) | class CppProgram
FILE: h/ErrorHandler.h
type ErrorPriority (line 11) | enum ErrorPriority
function class (line 20) | class ErrorHandler
function class (line 39) | class PineconeError
FILE: h/Namespace.h
type shared_ptr (line 18) | typedef shared_ptr<NamespaceData> Namespace;
function class (line 26) | class NamespaceData: public std::enable_shared_from_this<NamespaceData>
FILE: h/Operator.h
function class (line 15) | class OperatorData
type shared_ptr (line 58) | typedef shared_ptr<OperatorData> Operator;
FILE: h/PineconeProgram.h
function class (line 31) | class PineconeProgram
FILE: h/SourceFile.h
function class (line 6) | class SourceFile
FILE: h/StackFrame.h
function class (line 12) | class StackFrame
FILE: h/Token.h
function class (line 15) | class TokenData
function isComment (line 51) | bool isComment() {return tokenType==LINE_COMMENT || tokenType==BLOCK_COM...
type shared_ptr (line 67) | typedef shared_ptr<TokenData> Token;
FILE: h/Type.h
type shared_ptr (line 18) | typedef shared_ptr<TypeBase> Type;
type NamedType (line 32) | struct NamedType
type OffsetAndType (line 38) | struct OffsetAndType
function class (line 44) | class TypeBase: public std::enable_shared_from_this<TypeBase>
function class (line 135) | class TupleTypeMaker
FILE: h/utils/stringArray.h
function namespace (line 5) | namespace str
FILE: h/utils/stringDrawing.h
function namespace (line 5) | namespace str
FILE: h/utils/stringNumConversion.h
function namespace (line 5) | namespace str
FILE: h/utils/stringUtils.h
function namespace (line 12) | namespace str
FILE: src/Actions/Action.cpp
function string (line 19) | string ActionData::toString()
function string (line 26) | string ActionData::getTypesString()
class VoidAction (line 35) | class VoidAction: public ActionData
method VoidAction (line 38) | VoidAction(): ActionData(Void, Void, Void)
method addToProg (line 48) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
method string (line 54) | string getDescription()
class LambdaAction (line 60) | class LambdaAction: public ActionData
method LambdaAction (line 63) | LambdaAction(Type inLeftTypeIn, Type inRightTypeIn, Type returnTypeIn,
method addToProg (line 101) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
method string (line 106) | string getDescription()
function Action (line 117) | Action lambdaAction(Type inLeftTypeIn, Type inRightTypeIn, Type returnTy...
function Action (line 125) | Action createNewVoidAction()
FILE: src/Actions/BoolOpAction.cpp
class AndAction (line 5) | class AndAction: public ActionData
method AndAction (line 9) | AndAction(Action firstActionIn, Action secondActionIn)
method string (line 26) | string getDescription()
method addToProg (line 55) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
class OrAction (line 74) | class OrAction: public ActionData
method OrAction (line 78) | OrAction(Action firstActionIn, Action secondActionIn)
method string (line 95) | string getDescription()
method addToProg (line 123) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
function Action (line 142) | Action andAction(Action firstActionIn, Action secondActionIn)
function Action (line 147) | Action orAction(Action firstActionIn, Action secondActionIn)
FILE: src/Actions/BranchAction.cpp
class BranchAction (line 6) | class BranchAction: public ActionData
method BranchAction (line 9) | BranchAction(Action leftInputIn, Action actionIn, Action rightInputIn)
method string (line 46) | string getDescription()
method addToProg (line 69) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
class RightBranchAction (line 89) | class RightBranchAction: public ActionData
method RightBranchAction (line 92) | RightBranchAction(Action actionIn, Action rightInputIn)
method string (line 120) | string getDescription()
method addToProg (line 141) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
class LeftBranchAction (line 156) | class LeftBranchAction: public ActionData
method LeftBranchAction (line 159) | LeftBranchAction(Action leftInputIn, Action actionIn)
method string (line 182) | string getDescription()
method addToProg (line 203) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
function Action (line 218) | Action branchAction(Action leftInputIn, Action actionIn, Action rightInp...
FILE: src/Actions/FunctionAction.cpp
class FunctionAction (line 12) | class FunctionAction: public ActionData
method FunctionAction (line 16) | FunctionAction(Action actionIn, shared_ptr<StackFrame> stackFameIn):
method FunctionAction (line 31) | FunctionAction(AstNode nodeIn, Type returnTypeIn, shared_ptr<StackFram...
method resolveAction (line 41) | void resolveAction()
method string (line 64) | string getDescription()
method isFunction (line 72) | bool isFunction() {return true;}
method addToProg (line 97) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
function Action (line 213) | Action functionAction(Action actionIn, shared_ptr<StackFrame> stackFameIn)
function Action (line 218) | Action functionAction(AstNode nodeIn, Type returnTypeIn, shared_ptr<Stac...
FILE: src/Actions/IfAction.cpp
class IfAction (line 4) | class IfAction: public ActionData
method IfAction (line 8) | IfAction(Action conditionIn, Action ifActionIn)
method string (line 30) | string getDescription()
method addToProg (line 47) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
class IfElseAction (line 65) | class IfElseAction: public ActionData
method IfElseAction (line 69) | IfElseAction(Action conditionIn, Action ifActionIn, Action elseActionIn)
method string (line 93) | string getDescription()
method addToProg (line 131) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
function Action (line 173) | Action ifAction(Action conditionIn, Action ifActionIn)
function Action (line 178) | Action ifElseAction(Action conditionIn, Action ifActionIn, Action elseAc...
FILE: src/Actions/ListAction.cpp
class ListAction (line 4) | class ListAction: public ActionData
method ListAction (line 8) | ListAction(const vector<Action>& actionsIn, const vector<Action>& dest...
method string (line 32) | string getDescription()
method addToProg (line 96) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
method addToProg (line 101) | void addToProg(CppProgram* prog, Type returnType)
function addListToProgWithCppCasting (line 167) | void addListToProgWithCppCasting(ListAction* list, Type returnType, CppP...
function Action (line 172) | Action listAction(const vector<Action>& actionsIn, const vector<Action>&...
FILE: src/Actions/LoopAction.cpp
class LoopAction (line 4) | class LoopAction: public ActionData
method LoopAction (line 8) | LoopAction(Action conditionIn, Action endActionIn, Action loopActionIn)
method string (line 31) | string getDescription()
method addToProg (line 78) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
function Action (line 104) | Action loopAction(Action conditionIn, Action loopActionIn)
function Action (line 109) | Action loopAction(Action conditionIn, Action endActionIn, Action loopAct...
FILE: src/Actions/MakeTupleAction.cpp
class GetElemFromTupleAction (line 9) | class GetElemFromTupleAction
method GetElemFromTupleAction (line 261) | GetElemFromTupleAction(Type typeInIn, string nameIn):
method string (line 272) | string getDescription()
method addToProg (line 285) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
class CppTupleCastAction (line 10) | class CppTupleCastAction
method CppTupleCastAction (line 143) | CppTupleCastAction(Action actionIn, Type returnType):
method string (line 154) | string getDescription()
method addToProg (line 164) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
class ListAction (line 12) | class ListAction
class MakeTupleAction (line 15) | class MakeTupleAction: public ActionData
method MakeTupleAction (line 19) | MakeTupleAction(const vector<Action>& sourceActionsIn):
method string (line 57) | string getDescription()
method addToProg (line 109) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
class CppTupleCastAction (line 139) | class CppTupleCastAction: public ActionData
method CppTupleCastAction (line 143) | CppTupleCastAction(Action actionIn, Type returnType):
method string (line 154) | string getDescription()
method addToProg (line 164) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
class GetElemFromTupleAction (line 257) | class GetElemFromTupleAction: public ActionData
method GetElemFromTupleAction (line 261) | GetElemFromTupleAction(Type typeInIn, string nameIn):
method string (line 272) | string getDescription()
method addToProg (line 285) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
function Action (line 347) | Action makeTupleAction(const std::vector<Action>& sourceActionsIn)
function Action (line 352) | Action getElemFromTupleAction(Type source, string name)
function Action (line 362) | Action cppTupleCastAction(Action actionIn, Type returnType)
FILE: src/Actions/TypeAction.cpp
class TypeGetAction (line 4) | class TypeGetAction: public ActionData
method TypeGetAction (line 8) | TypeGetAction(Type typeIn):
method string (line 14) | string getCSource(string inLeft, string inRight)
method string (line 26) | string getDescription()
function Action (line 34) | Action typeGetAction(Type typeIn)
FILE: src/Actions/VarAction.cpp
class VarGetAction (line 9) | class VarGetAction: public ActionData
method VarGetAction (line 13) | VarGetAction(size_t in, void ** stackPtrPtrIn, Type typeIn, string idIn):
method addToProg (line 36) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
method string (line 61) | string getDescription()
class VarSetAction (line 72) | class VarSetAction: public ActionData
method VarSetAction (line 76) | VarSetAction(size_t in, void ** stackPtrPtrIn, Type typeIn, string idIn):
method addToProg (line 103) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
method string (line 147) | string getDescription()
class ConstGetAction (line 158) | class ConstGetAction: public ActionData
method ConstGetAction (line 162) | ConstGetAction(const void* in, Type typeIn, string textIn):
method addToProg (line 183) | void addToProg(Action inLeft, Action inRight, CppProgram* prog)
method string (line 241) | string getDescription()
function Action (line 251) | Action varGetAction(size_t in, Type typeIn, string textIn)
function Action (line 256) | Action varSetAction(size_t in, Type typeIn, string varNameIn)
function Action (line 261) | Action globalGetAction(size_t in, Type typeIn, string textIn)
function Action (line 266) | Action globalSetAction(size_t in, Type typeIn, string textIn)
function Action (line 271) | Action constGetAction(const void* in, Type typeIn, string textIn, Namesp...
FILE: src/AstNode.cpp
function string (line 33) | string AstList::getString()
function string (line 98) | string AstFuncBody::getString()
function AstNode (line 113) | AstNode AstFuncBody::makeCopyWithSpecificTypes(Type leftInType, Type rig...
function string (line 167) | string AstExpression::getString()
function string (line 223) | string AstConstExpression::getString()
function string (line 265) | string AstOpWithInput::getString()
function string (line 496) | string AstToken::getString()
function string (line 609) | string AstTuple::getString()
function string (line 637) | string AstTokenType::getString()
function string (line 650) | string AstTupleType::getString()
FILE: src/CppProgram.cpp
function string (line 7) | string getValidCppId(string in)
function string (line 156) | string CppNameContainer::getCpp(const string& pn)
function string (line 303) | string CppFuncBase::pnToCpp(const string& in)
function string (line 372) | string CppProgram::getTypeCode(Type in)
function string (line 670) | string CppProgram::getCppCode()
FILE: src/ErrorHandler.cpp
function string (line 13) | string ErrorHandler::priorityToStr(ErrorPriority in)
FILE: src/Lexer.cpp
class CharClassifier (line 13) | class CharClassifier
type Type (line 16) | enum Type
function lexString (line 192) | void lexString(shared_ptr<SourceFile> file, vector<Token>& tokens)
FILE: src/Namespace.cpp
function Namespace (line 32) | Namespace NamespaceData::makeRootNamespace()
function Namespace (line 37) | Namespace NamespaceData::makeChild()
function Namespace (line 42) | Namespace NamespaceData::makeChildAndFrame(string nameIn)
function string (line 54) | string NamespaceData::getString()
function string (line 112) | string NamespaceData::getStringWithParents()
function Action (line 160) | Action NamespaceData::addVar(Type type, string name)
function Type (line 256) | Type NamespaceData::getType(string name, bool throwSourceError, Token to...
function Action (line 285) | Action NamespaceData::getDestroyer(Type type)
function Action (line 312) | Action NamespaceData::wrapInDestroyer(Action in)
function Action (line 323) | Action NamespaceData::getCopier(Type type)
function Action (line 350) | Action NamespaceData::getActionForTokenWithInput(Token token, Type left,...
FILE: src/Parser.cpp
function AstNode (line 60) | AstNode astNodeFromTokens(const vector<Token>& tokens, int left, int right)
function skipBrace (line 80) | int skipBrace(const vector<Token>& tokens, int start)
function findExpressionSplit (line 273) | int findExpressionSplit(const vector<Token>& tokens, int left, int right)
function AstNode (line 315) | AstNode parseExpression(const vector<Token>& tokens, int left, int right)
function parseTokenList (line 523) | void parseTokenList(const vector<Token>& tokens, int left, int right, ve...
function parseSequence (line 641) | void parseSequence(const vector<Token>& tokens, int left, int right, Ope...
function parseType (line 673) | unique_ptr<AstType> parseType(const vector<Token>& tokens, int left, int...
function importFile (line 759) | void importFile(vector<AstNode>& nodes, string path)
FILE: src/PineconeProgram.cpp
function string (line 132) | string PineconeProgram::getCpp()
FILE: src/PineconeStdLib.cpp
function string (line 83) | string getText(Operator op) {return op->getText();}
function string (line 84) | string getText(string in) {return in;}
function addConst (line 86) | void addConst(void* data, Type type, string name)
function addAction (line 92) | void addAction(T id, Type leftType, Type rightType, Type returnType, fun...
function addType (line 97) | void addType(Type type, string id)
function stringToLambda (line 104) | function<void(Action inLeft, Action inRight, CppProgram* prog)> stringTo...
function addAction (line 160) | void addAction(string text, Type leftType, Type rightType, Type returnTy...
function addAction (line 165) | void addAction(Operator op, Type leftType, Type rightType, Type returnTy...
function T (line 174) | inline T getValFromTuple(void* data, Type type, string name)
function setValInTuple (line 208) | inline void setValInTuple(void* data, Type type, string name, T val)
function string (line 224) | inline string pncnStr2CppStr(void* obj)
function addToProgPnStr (line 249) | void addToProgPnStr(CppProgram * prog)
function addToProgCStr (line 266) | void addToProgCStr(CppProgram * prog)
function addToProgSubStr (line 284) | void addToProgSubStr(CppProgram * prog)
function addToProgIntToStr (line 299) | void addToProgIntToStr(CppProgram * prog)
function addToProgStrToInt (line 330) | void addToProgStrToInt(CppProgram * prog)
function addToProgStrToDub (line 354) | void addToProgStrToDub(CppProgram * prog)
function addToProgConcatStr (line 388) | void addToProgConcatStr(CppProgram * prog)
function addToProgDoubleToStr (line 404) | void addToProgDoubleToStr(CppProgram * prog)
function addToProgAsciiToStr (line 426) | void addToProgAsciiToStr(CppProgram * prog)
function addToProgGetInputLine (line 440) | void addToProgGetInputLine(CppProgram * prog)
function addToProgEqStr (line 468) | void addToProgEqStr(CppProgram * prog)
function addToProgRunCmd (line 487) | void addToProgRunCmd(CppProgram * prog)
function addToProgMakeIntArray (line 516) | void addToProgMakeIntArray(CppProgram * prog)
function addToProgStrWithEscapedNames (line 529) | void addToProgStrWithEscapedNames(CppProgram * prog, string str)
function basicSetup (line 573) | void basicSetup()
function populateBasicTypes (line 581) | void populateBasicTypes()
function populateConstants (line 594) | void populateConstants()
function populateOperators (line 710) | void populateOperators()
function populateConverters (line 892) | void populateConverters()
function populateStdFuncs (line 1085) | void populateStdFuncs()
function populateTypeInfoFuncs (line 1157) | void populateTypeInfoFuncs()
function populateMemManagementFuncs (line 1222) | void populateMemManagementFuncs()
function populateStringFuncs (line 1337) | void populateStringFuncs()
function populateArrayFuncs (line 1622) | void populateArrayFuncs()
function populateIntArrayAndFuncs (line 1914) | void populateIntArrayAndFuncs()
function populateNonStdFuncs (line 2009) | void populateNonStdFuncs()
function populateCppInterfaceFuncs (line 2067) | void populateCppInterfaceFuncs()
function populatePineconeStdLib (line 2092) | void populatePineconeStdLib()
FILE: src/ResolveLiteral.cpp
function Action (line 8) | Action resolveIntLiteral(Token token, Type type)
function Action (line 37) | Action resolveDubLiteral(Token token)
function Action (line 84) | Action resolveStringLiteral(Token token)
function Action (line 102) | Action resolveLiteral(Token token)
FILE: src/SourceFile.cpp
function string (line 20) | string SourceFile::getDirPath()
function string (line 33) | string SourceFile::getBoxedString()
function string (line 38) | string SourceFile::getLine(int lineNum)
FILE: src/StackFrame.cpp
function Type (line 53) | Type StackFrame::getLeftInType()
function Type (line 65) | Type StackFrame::getRightInType()
FILE: src/Token.cpp
function Token (line 5) | Token makeToken(string textIn, shared_ptr<SourceFile> fileIn, int lineIn...
function Token (line 12) | Token makeToken(string textIn)
function string (line 17) | string TokenData::typeToString(TokenData::Type in)
function string (line 35) | string TokenData::getDescription()
function string (line 40) | string TokenData::getTypeDescription()
function string (line 61) | string tableStringFromTokens(const vector<Token>& tokens, string tableName)
function string (line 137) | string stringFromTokens(const vector<Token>& tokens, int left, int right)
FILE: src/Type.cpp
class VoidType (line 11) | class VoidType: public TypeBase
method string (line 14) | virtual string getString()
method string (line 19) | string getCompactString()
method string (line 24) | string getCppLiteral(void * data, CppProgram * prog)
method isCreatable (line 29) | bool isCreatable()
method isVoid (line 34) | bool isVoid()
method getSize (line 39) | size_t getSize()
method PrimitiveType (line 44) | PrimitiveType getType()
method matchesSameTypeType (line 51) | bool matchesSameTypeType(Type other)
class UnknownType (line 57) | class UnknownType: public TypeBase
method string (line 60) | virtual string getString()
method string (line 65) | string getCompactString()
method string (line 70) | string getCppLiteral(void * data, CppProgram * prog)
method isCreatable (line 75) | bool isCreatable()
method isVoid (line 80) | bool isVoid()
method getSize (line 85) | size_t getSize()
method PrimitiveType (line 90) | PrimitiveType getType()
method matchesSameTypeType (line 97) | bool matchesSameTypeType(Type other)
class PrimType (line 103) | class PrimType: public TypeBase
method PrimType (line 107) | PrimType(PrimitiveType in)
method string (line 112) | string getCompactString()
method string (line 126) | string getString()
method string (line 131) | string getCppLiteral(void * data, CppProgram * prog)
method getSize (line 155) | size_t getSize()
method PrimitiveType (line 169) | PrimitiveType getType()
method matchesSameTypeType (line 178) | bool matchesSameTypeType(Type other)
class TupleType (line 184) | class TupleType: public TypeBase
method TupleType (line 188) | TupleType(unique_ptr<vector<NamedType>> in, bool isAnonymousIn)
method string (line 216) | string getString()
method string (line 235) | string getCompactString()
method string (line 252) | string getCppLiteral(void * data, CppProgram * prog)
method getSize (line 277) | size_t getSize()
method PrimitiveType (line 289) | PrimitiveType getType()
method OffsetAndType (line 294) | OffsetAndType getSubType(string name)
method isWhatev (line 314) | bool isWhatev()
method isCreatable (line 319) | bool isCreatable()
method Type (line 324) | Type actuallyIs(Type target)
method matchesSameTypeType (line 352) | bool matchesSameTypeType(Type other)
class PtrType (line 385) | class PtrType: public TypeBase
method PtrType (line 389) | PtrType(Type in)
method string (line 394) | string getString()
method string (line 399) | string getCompactString()
method string (line 404) | string getCppLiteral(void * data, CppProgram * prog)
method getSize (line 412) | size_t getSize()
method PrimitiveType (line 417) | PrimitiveType getType()
method Type (line 422) | Type getSubType()
method Type (line 427) | Type actuallyIs(Type target)
method matchesSameTypeType (line 436) | bool matchesSameTypeType(Type other)
class MetaType (line 442) | class MetaType: public TypeBase
method MetaType (line 446) | MetaType(Type in)
method string (line 451) | string getString()
method string (line 456) | string getCompactString()
method string (line 461) | string getCppLiteral(void * data, CppProgram * prog)
method getSize (line 466) | size_t getSize()
method isCreatable (line 471) | bool isCreatable()
method PrimitiveType (line 476) | PrimitiveType getType()
method Type (line 481) | Type getSubType()
method isWhatev (line 486) | bool isWhatev()
method Type (line 491) | Type actuallyIs(Type target)
method matchesSameTypeType (line 500) | bool matchesSameTypeType(Type other)
class WhatevType (line 506) | class WhatevType: public TypeBase
method WhatevType (line 510) | WhatevType() {}
method string (line 512) | string getString()
method string (line 517) | string getCompactString()
method isCreatable (line 522) | bool isCreatable()
method string (line 527) | string getCppLiteral(void * data, CppProgram * prog)
method getSize (line 532) | size_t getSize()
method PrimitiveType (line 537) | PrimitiveType getType()
method isWhatev (line 542) | bool isWhatev()
method Type (line 547) | Type getSubType()
method Type (line 552) | Type actuallyIs(Type target)
method matchesSameTypeType (line 561) | bool matchesSameTypeType(Type other)
function Type (line 567) | Type TypeBase::makeNewVoid()
function Type (line 572) | Type TypeBase::makeNewPrimitive(PrimitiveType typeIn)
function Type (line 577) | Type TypeBase::makeNewWhatev()
function Type (line 596) | Type TypeBase::getMeta()
function Type (line 601) | Type TypeBase::getPtr()
function string (line 609) | string TypeBase::getString(PrimitiveType in)
function Type (line 661) | Type TypeBase::actuallyIs(Type target)
function Type (line 676) | Type makeTuple(const vector<NamedType>& in, bool isAnonymous)
function Type (line 709) | Type TupleTypeMaker::get(bool isAnonymous)
function string (line 719) | string TupleTypeMaker::getUniqueName()
FILE: src/main.cpp
type Flags (line 14) | struct Flags
function main (line 30) | int main(int argc, char ** argv)
function Flags (line 169) | Flags getFlags(int argc, char ** argv)
FILE: src/msclStringFuncs.cpp
function substringMatches (line 16) | bool substringMatches(const string& in, int pos, const string& subStr)
function searchInString (line 31) | int searchInString(const string& in, const string& pattern, int startPos)
function string (line 42) | string replaceSubstring(const string& in, const string& searchFor, const...
function sliceStringBy (line 66) | void sliceStringBy(const string& in, const string& pattern, vector<strin...
function string (line 86) | string indentString(const string& in, string indent, int level)
function string (line 111) | string tabsToSpaces(const string& in, int spaceNum)
function tabsToSpaces (line 146) | void tabsToSpaces(vector<string>& in)
function string (line 154) | string padString(const string& in, int size, int alignment, string pad,...
function string (line 209) | string getTextOfLine(const string& in, int lineNum)
function string (line 254) | string lineListToBoxedString(const vector<string>& in, string boxName, i...
function string (line 333) | string putStringInBox(const string& in, string boxName, bool showLineNum...
function string (line 351) | string putStringInTable(const string& in, string tableName)
function string (line 440) | string doubleToString(double in)
function stringToInt (line 453) | int stringToInt(string in)
function stringToDouble (line 473) | double stringToDouble(string in)
function string (line 503) | string loadEntireFile(string inName, bool printOutput)
function writeFile (line 535) | bool writeFile(const string& filename, const string& contents, bool debug)
function getRandChar (line 596) | char getRandChar()
function string (line 621) | string getUniqueString(string hint, std::function<bool (string)> checker...
function string (line 655) | string runCmd(string cmd, bool printOutput) // if print output is false,...
function getTermWidth (line 683) | int getTermWidth()
FILE: src/utils/fileUtils.cpp
function loadFile (line 9) | void loadFile(string filepath, string& contents)
function writeFile (line 28) | void writeFile(string filepath, const string& contents)
FILE: src/utils/stringArray.cpp
type str (line 3) | namespace str
function getMaxWidth (line 6) | int getMaxWidth(vector<string>& in)
function padWidths (line 21) | void padWidths(vector<string>& out, int size, StringPadAlignment align...
function string (line 34) | string join(vector<string>& in, string joiner, bool addAtEnd)
FILE: src/utils/stringDrawing.cpp
type str (line 9) | namespace str
function string (line 15) | string getBoxedString(const string& in, string boxName, bool showLineN...
function putArrayInTreeNodeBox (line 111) | void putArrayInTreeNodeBox(vector<string>& data)
function string (line 124) | string putStringInTreeNodeBox(const string& in)
function string (line 132) | string makeList(vector<string>& data)
function string (line 166) | string makeRootUpBinaryTree(const string& root, const string& leftBran...
FILE: src/utils/stringNumConversion.cpp
type str (line 4) | namespace str
function string (line 7) | string charToCppStringLiteralEscaped(unsigned char c)
function string (line 20) | string intToBase62(unsigned int num, int maxDigits)
function string (line 53) | string ptrToUniqueStr(void* ptrIn, int digits)
FILE: src/utils/stringUtils.cpp
type str (line 4) | namespace str
function splitBy (line 7) | void splitBy(vector<string>& out, const string& in, const string& spli...
function string (line 36) | string pad(const string& in, int size, StringPadAlignment alignment, s...
function string (line 94) | string tabsToSpaces(const string& in, int tabWidth)
function getGlyphPosOf (line 131) | int getGlyphPosOf(const string& in, string pattern)
Condensed preview — 111 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (381K chars).
[
{
"path": ".gitignore",
"chars": 267,
"preview": "\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*Valgr"
},
{
"path": "LICENSE",
"chars": 1070,
"preview": "MIT License\n\nCopyright (c) 2017 Sophie Winter\n\nPermission is hereby granted, free of charge, to any person obtaining a c"
},
{
"path": "Makefile",
"chars": 257,
"preview": "# 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 tha"
},
{
"path": "_config.yml",
"chars": 26,
"preview": "theme: jekyll-theme-hacker"
},
{
"path": "changelog.md",
"chars": 1781,
"preview": "# Pinecone Changelog\nThis file documents all major changes to the Pinecone langauge.\nEvery new version gets a number of "
},
{
"path": "codeblocks/Pinecone.cbp",
"chars": 4718,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n<CodeBlocks_project_file>\n\t<FileVersion major=\"1\" minor=\"6\" />\n"
},
{
"path": "codeblocks/readme.md",
"chars": 175,
"preview": "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 Co"
},
{
"path": "examples/brainfuck.pn",
"chars": 2004,
"preview": "\n//\nThis is an interpreter for the esoteric programming language brainfuck\n\\\\\n\ndata: IntArray: 40000\noffset: 0\nerror: fl"
},
{
"path": "examples/fizzBuzz.pn",
"chars": 393,
"preview": "# FizzBuzz\n\n# call the function defined below\nfizzBuzz: 1, 20\n\n# define the FizzBuzz function\nfizzBuzz :: {start: Int, e"
},
{
"path": "examples/hello_world.pn",
"chars": 23,
"preview": "print: \"Hello World!\"\n\n"
},
{
"path": "examples/historical/snake_original.pn",
"chars": 1341,
"preview": "# this was written on Jan 12th, 2016.\n# this is the first complex pinecone program ever wretten.\n# type the numbers 1, 2"
},
{
"path": "examples/incomplete/hashmap.pn",
"chars": 939,
"preview": "\nHashmap :: {used: IntArray, keys: IntArray, vals: IntArray}\n\nHashmap :: {} -> {Hashmap}:\n(\n\tsize: 10\n\tused: (IntArray: "
},
{
"path": "examples/morse.pn",
"chars": 1035,
"preview": "# this program converts text into morse code\n\n# this constant string will act as the data source for the conversion\nkey "
},
{
"path": "examples/queue.pn",
"chars": 1653,
"preview": "# this is an implementation of a queue using a dynamically sized circular buffer\n# this was wretten for Pinecone v0.3, w"
},
{
"path": "examples/readme.md",
"chars": 56,
"preview": "These are some examples of working Pinecone source code\n"
},
{
"path": "examples/simple_demo.pn",
"chars": 991,
"preview": "\n//\nThis file demonstrates the basic syntax constructs of Pinecone\n\nto run, simply run command\npath/to/pinecone/executab"
},
{
"path": "examples/snake_new.pn",
"chars": 1314,
"preview": "# this is an updated version of the original Pinecone snake game\n# use WASD to move\n\nw :: 16\nh :: 8\n\nmeChar :: 79\ntrailC"
},
{
"path": "h/Action.h",
"chars": 3529,
"preview": "#pragma once\n\n#include \"StackFrame.h\"\n#include \"Type.h\"\n#include \"CppProgram.h\"\n#include <functional>\n#include <memory>\n"
},
{
"path": "h/AllOperators.h",
"chars": 4228,
"preview": "#pragma once\n\n#include <vector>\nusing std::vector;\n\n#include <unordered_map>\nusing std::unordered_map;\n\n#include \"Operat"
},
{
"path": "h/AstNode.h",
"chars": 13996,
"preview": "#pragma once\n\n#include \"Token.h\"\n#include \"Action.h\"\n#include \"ErrorHandler.h\"\n\nclass NamespaceData;\ntypedef shared_ptr<"
},
{
"path": "h/CppProgram.h",
"chars": 4330,
"preview": "#pragma once\n\n#include \"Type.h\"\n\n#include <map>\n\n#include <unordered_set>\n\n// Pinecone names that are hardcoded should s"
},
{
"path": "h/ErrorHandler.h",
"chars": 968,
"preview": "#pragma once\n\n#include \"Token.h\"\n\n#include <string>\nusing std::string;\n\n#define FUNC string(__FUNCTION__)\n//#define FUNC"
},
{
"path": "h/Namespace.h",
"chars": 4144,
"preview": "#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#incl"
},
{
"path": "h/Operator.h",
"chars": 1282,
"preview": "#pragma once\n\nclass TokenData;\n\n#include <memory>\nusing std::shared_ptr;\n\n#include <string>\nusing std::string;\n\nclass Al"
},
{
"path": "h/PineconeProgram.h",
"chars": 1064,
"preview": "#pragma once\n\n#include \"VERSION.h\"\n\n#include <string>\n#include <iostream>\n#include <math.h>\n#include <vector>\n#include <"
},
{
"path": "h/SourceFile.h",
"chars": 682,
"preview": "#pragma once\n\n#include <string>\nusing std::string;\n\nclass SourceFile\n{\npublic:\n\t\n\tSourceFile()\n\t{\n\t\tfilename=\"[empty_fil"
},
{
"path": "h/StackFrame.h",
"chars": 674,
"preview": "#pragma once\n\n#include <vector>\nusing std::vector;\n\n#include \"Type.h\"\n//#include \"Action.h\"\n\nextern void* globalFramePtr"
},
{
"path": "h/Token.h",
"chars": 1613,
"preview": "#pragma once\n\n#include \"Operator.h\"\n\n#include <string>\nusing std::string;\n\n#include <vector>\nusing std::vector;\n\nclass S"
},
{
"path": "h/Type.h",
"chars": 3447,
"preview": "#pragma once\n\n#include <string>\nusing std::string;\n\n#include <vector>\nusing std::vector;\n\n#include <memory>\nusing std::s"
},
{
"path": "h/VERSION.h",
"chars": 121,
"preview": "#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;"
},
{
"path": "h/msclStringFuncs.h",
"chars": 6027,
"preview": "#pragma once\n\n#include \"PineconeProgram.h\"\n\n#include <string>\nusing std::string;\nusing std::to_string;\n\n#include <vector"
},
{
"path": "h/utils/fileUtils.h",
"chars": 149,
"preview": "\n#pragma once\n\n#include \"stringUtils.h\"\n\nvoid loadFile(string filepath, string& contents);\nvoid writeFile(string filepat"
},
{
"path": "h/utils/stringArray.h",
"chars": 804,
"preview": "#pragma once\n\n#include \"stringUtils.h\"\n\nnamespace str\n{\n\nvoid splitBy(vector<string>& out, const string& in, const strin"
},
{
"path": "h/utils/stringDrawing.h",
"chars": 702,
"preview": "#pragma once\n\n#include \"stringUtils.h\"\n\nnamespace str\n{\n\n// if max width is -1, it will autodetect\nstring getBoxedString"
},
{
"path": "h/utils/stringNumConversion.h",
"chars": 550,
"preview": "#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 li"
},
{
"path": "h/utils/stringUtils.h",
"chars": 3002,
"preview": "\n#pragma once\n\n/// This string util header will slowly replace msclStringFuncs.h\n\n#include <string>\nusing std::string;\n\n"
},
{
"path": "other/pinecone.pn",
"chars": 84,
"preview": "\nprint: argLen.String + \" args:\"\n\ni: 0 | i < argLen | i: i + 1 @ (\n\tprint: arg: i\n)\n"
},
{
"path": "other/pinecone_concept.txt",
"chars": 5053,
"preview": "# Programming language concept by Sophie Winter\n# This is not ment to be actual code, just a place to exparament with di"
},
{
"path": "other/readme.md",
"chars": 78,
"preview": "this directory is for miscellaneous files that don't really go anywhere else.\n"
},
{
"path": "other/user_testing.txt",
"chars": 1167,
"preview": "# what do you think the following code snippits mean?\n\n# 1 _____________________________________________________________"
},
{
"path": "readme.md",
"chars": 5080,
"preview": "# The Pinecone Programming Language\n**_Built from the ground up to be fast, concise and intuitive._**\n\n## NOTE: PINECONE"
},
{
"path": "repl/readme.md",
"chars": 619,
"preview": "\n## Repl\n`repl.sh` is a BASH script that creates a Pinecone repl. It supports calling functions and variables, but does "
},
{
"path": "repl/repl.sh",
"chars": 374,
"preview": "#!/bin/bash\necho \"\" > ./repl/tmp.pn;\n\nwhile [ true ]\ndo\n read -p \"> \" cmd;\n if [ \"$cmd\" == \".clear\" ]; then\n echo \""
},
{
"path": "src/Actions/Action.cpp",
"chars": 2967,
"preview": "#include \"../../h/Action.h\"\n\n#include \"../../h/ErrorHandler.h\"\n\n#include \"../../h/msclStringFuncs.h\"\n\nActionData::Action"
},
{
"path": "src/Actions/BoolOpAction.cpp",
"chars": 3388,
"preview": "#include \"../../h/Action.h\"\n#include \"../../h/ErrorHandler.h\"\n#include \"../../h/utils/stringDrawing.h\"\n\nclass AndAction:"
},
{
"path": "src/Actions/BranchAction.cpp",
"chars": 8096,
"preview": "#include \"../../h/Action.h\"\n#include \"../../h/ErrorHandler.h\"\n#include \"../../h/CppProgram.h\"\n#include \"../../h/utils/st"
},
{
"path": "src/Actions/FunctionAction.cpp",
"chars": 5998,
"preview": "\n#include \"../../h/Action.h\"\n#include \"../../h/ErrorHandler.h\"\n#include \"../../h/StackFrame.h\"\n#include \"../../h/AstNode"
},
{
"path": "src/Actions/IfAction.cpp",
"chars": 4723,
"preview": "#include \"../../h/Action.h\"\n#include \"../../h/ErrorHandler.h\"\n\nclass IfAction: public ActionData\n{\npublic:\n\t\n\tIfAction(A"
},
{
"path": "src/Actions/ListAction.cpp",
"chars": 3214,
"preview": "#include \"../../h/Action.h\"\n#include \"../../h/ErrorHandler.h\"\n\nclass ListAction: public ActionData\n{\npublic:\n\t\n\tListActi"
},
{
"path": "src/Actions/LoopAction.cpp",
"chars": 2587,
"preview": "#include \"../../h/Action.h\"\n#include \"../../h/ErrorHandler.h\"\n\nclass LoopAction: public ActionData\n{\npublic:\n\t\n\tLoopActi"
},
{
"path": "src/Actions/MakeTupleAction.cpp",
"chars": 7989,
"preview": "#include \"../../h/Action.h\"\n#include \"../../h/ErrorHandler.h\"\n\n#include <vector>\n#include <typeinfo>\n\nusing std::vector;"
},
{
"path": "src/Actions/TypeAction.cpp",
"chars": 726,
"preview": "#include \"../../h/Action.h\"\n#include \"../../h/ErrorHandler.h\"\n\nclass TypeGetAction: public ActionData\n{\npublic:\n\t\n\tTypeG"
},
{
"path": "src/Actions/VarAction.cpp",
"chars": 6629,
"preview": "#include \"../../h/Action.h\"\n#include \"../../h/ErrorHandler.h\"\n#include \"../../h/StackFrame.h\"\n#include \"../../h/CppProgr"
},
{
"path": "src/AllOperators.cpp",
"chars": 2229,
"preview": "\n\n#include \"../h/AllOperators.h\"\n#include \"../h/ErrorHandler.h\"\n\n//shared_ptr<AllOperators> ops(nullptr);\nAllOperators* "
},
{
"path": "src/AstNode.cpp",
"chars": 16205,
"preview": "#include \"../h/AstNode.h\"\n#include \"../h/Namespace.h\"\n#include \"../h/ErrorHandler.h\"\n#include \"../h/msclStringFuncs.h\"\n#"
},
{
"path": "src/CppProgram.cpp",
"chars": 16025,
"preview": "#include \"../h/CppProgram.h\"\n#include \"../h/msclStringFuncs.h\"\n\n#include <map>\n#include <unordered_set>\n\nstring getValid"
},
{
"path": "src/ErrorHandler.cpp",
"chars": 1940,
"preview": "\n#include \"../h/ErrorHandler.h\"\n#include \"../h/msclStringFuncs.h\"\n#include \"../h/SourceFile.h\"\n\n#include <iostream>\n\nusi"
},
{
"path": "src/Lexer.cpp",
"chars": 5477,
"preview": "#include \"../h/Token.h\"\n#include \"../h/ErrorHandler.h\"\n#include \"../h/Operator.h\"\n#include \"../h/AllOperators.h\"\n#includ"
},
{
"path": "src/Namespace.cpp",
"chars": 10573,
"preview": "#include \"../h/Namespace.h\"\n#include \"../h/StackFrame.h\"\n#include \"../h/msclStringFuncs.h\"\n#include \"../h/ErrorHandler.h"
},
{
"path": "src/Parser.cpp",
"chars": 18648,
"preview": "#include \"../h/Token.h\"\n#include \"../h/AstNode.h\"\n#include \"../h/Namespace.h\"\n#include \"../h/ErrorHandler.h\"\n#include \"."
},
{
"path": "src/PineconeProgram.cpp",
"chars": 3196,
"preview": "#include \"../h/PineconeProgram.h\"\n#include \"../h/ErrorHandler.h\"\n#include \"../h/Operator.h\"\n#include \"../h/AllOperators."
},
{
"path": "src/PineconeStdLib.cpp",
"chars": 46500,
"preview": "#include \"../h/PineconeProgram.h\"\n#include \"../h/AllOperators.h\"\n#include \"../h/StackFrame.h\"\n#include \"../h/Namespace.h"
},
{
"path": "src/ResolveLiteral.cpp",
"chars": 3280,
"preview": "#include \"../h/Action.h\"\n#include \"../h/Token.h\"\n#include \"../h/ErrorHandler.h\"\n#include \"../h/Namespace.h\"\n\nextern Name"
},
{
"path": "src/SourceFile.cpp",
"chars": 674,
"preview": "#include \"../h/SourceFile.h\"\n#include \"../h/utils/fileUtils.h\"\n#include \"../h/msclStringFuncs.h\"\n\nSourceFile::SourceFile"
},
{
"path": "src/StackFrame.cpp",
"chars": 1903,
"preview": "#include \"../h/StackFrame.h\"\n#include \"../h/msclStringFuncs.h\"\n#include \"../h/ErrorHandler.h\"\n\nvoid* globalFramePtr=null"
},
{
"path": "src/Token.cpp",
"chars": 3114,
"preview": "#include \"../h/Token.h\"\n#include \"../h/msclStringFuncs.h\"\n#include \"../h/utils/stringUtils.h\"\n\nToken makeToken(string te"
},
{
"path": "src/Type.cpp",
"chars": 11953,
"preview": "#include \"../h/Type.h\"\n#include \"../h/ErrorHandler.h\"\n#include \"../h/CppProgram.h\"\n#include \"../h/msclStringFuncs.h\"\n\n#i"
},
{
"path": "src/main.cpp",
"chars": 6156,
"preview": "#include \"../h/msclStringFuncs.h\"\n#include \"../h/PineconeProgram.h\"\n#include \"../h/ErrorHandler.h\"\n\n#include <iostream>\n"
},
{
"path": "src/msclStringFuncs.cpp",
"chars": 12313,
"preview": "#include \"../h/msclStringFuncs.h\"\n\n#include <fstream>\n#include <sstream>\n#include <unistd.h> // for terminal size detect"
},
{
"path": "src/utils/fileUtils.cpp",
"chars": 691,
"preview": "\n#include \"../../h/utils/fileUtils.h\"\n\n#include <fstream>\n#include <sstream>\n\nusing std::stringstream;\n\nvoid loadFile(st"
},
{
"path": "src/utils/stringArray.cpp",
"chars": 725,
"preview": "#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"
},
{
"path": "src/utils/stringDrawing.cpp",
"chars": 6959,
"preview": "\n#include \"../../h/utils/stringDrawing.h\"\n#include \"../../h/utils/stringArray.h\"\n\n#include \"../../h/msclStringFuncs.h\"\n\n"
},
{
"path": "src/utils/stringNumConversion.cpp",
"chars": 847,
"preview": "#include \"../../h/utils/stringNumConversion.h\"\n#include <cstring> // for memcpy\n\nnamespace str\n{\n\nstring charToCppString"
},
{
"path": "src/utils/stringUtils.cpp",
"chars": 2685,
"preview": "#include \"../../h/utils/stringUtils.h\"\n#include <math.h>\n\nnamespace str\n{\n\nvoid splitBy(vector<string>& out, const strin"
},
{
"path": "tests/integration/brainfuck.pn",
"chars": 473,
"preview": "# Tests the Pinecone brainfuck interpreter\n\n# for the interpreter to be happy, there needs to be an extra newline at the"
},
{
"path": "tests/integration/morse.pn",
"chars": 378,
"preview": "# Tests my text to morse code converter\n\nprint: \"enter some text or type quit: .--. .. -. . -.-. --- -. . \\nenter some t"
},
{
"path": "tests/integration/queue.pn",
"chars": 1789,
"preview": "# this is a copy of the original file used for an intagration test\n# this is an implementation of a queue using a dynami"
},
{
"path": "tests/readme.md",
"chars": 310,
"preview": "This directory holds all tests for the Pinecone language. To run tests, open the parent directory in terminal and run\n`."
},
{
"path": "tests/regression/bool_short_circuit.pn",
"chars": 395,
"preview": "# Tests if short circuit is applied to operations with multiple bools\n\nprint: \"1\\nmyFunc called\\nmyFunc called\\nmyFunc c"
},
{
"path": "tests/regression/cpp_bad_escape_seq.pn",
"chars": 159,
"preview": "# Bad escape sequences can get into C++ transpiled code if a special char is followed by a hex digit\n\ntab: \"\\t\"\n\nprint: "
},
{
"path": "tests/regression/cpp_global_and_local_same_name.pn",
"chars": 170,
"preview": "# 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}: "
},
{
"path": "tests/regression/error_on_nonexistant_file.pn",
"chars": 289,
"preview": "# This test attempts to run the Pinecone interpreter on a nonexistant file, which should produce an error\n\nprint: \"error"
},
{
"path": "tests/regression/function_with_one_named_arg.pn",
"chars": 149,
"preview": "# test when there is a function that only has one argument which is named\n\nprint: \"8\\n_____\"\n\nmyFunc: 8\n\nmyFunc :: {arg:"
},
{
"path": "tests/regression/if_as_ternary.pn",
"chars": 157,
"preview": "# tests the if statement as a ternary operator, I think problem is if return type may always be void\n\nprint: \"yes\\n_____"
},
{
"path": "tests/regression/multiple_left_inputs.pn",
"chars": 233,
"preview": "# tests when there are multiple left inputs to a function\n# original but was caused to failing to skip {} in parsing an "
},
{
"path": "tests/regression/negative_literal.pn",
"chars": 105,
"preview": "# 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",
"chars": 248,
"preview": "# Pinecone test for source file without newline at the end of the file\n# IMPORTANT: many editors will automatically inse"
},
{
"path": "tests/run_tests.pn",
"chars": 4139,
"preview": "\npthslsh: \"/\"\n\nOS_IS_WINDOWS ?\n\tpthslsh: \"\\\\\"\n\nerrorDetails: String\n\nprint: \"pinecone v\"+VERSION.x.String+\".\"+VERSION.y."
},
{
"path": "tests/unfixed/backslash_in_block_comment.pn",
"chars": 298,
"preview": "# test with backslash in a block comment\n\nprint: \"this should print\\nthis should also print\\n_____\"\n\nprint: \"this should"
},
{
"path": "tests/unit/conditionals.pn",
"chars": 165,
"preview": "# 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"
},
{
"path": "tests/unit/constants.pn",
"chars": 81,
"preview": "# 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",
"chars": 373,
"preview": "# tests the calling of destroyers and copiers\n\nprint: \"copier called\\ncopier called\\n3\\ndestroyer called\\ndestroyer call"
},
{
"path": "tests/unit/funcs.pn",
"chars": 424,
"preview": "# 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\n"
},
{
"path": "tests/unit/generate_windows_line_endings.sh",
"chars": 118,
"preview": "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",
"chars": 148,
"preview": "# 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"
},
{
"path": "tests/unit/operators.pn",
"chars": 333,
"preview": "# 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"
},
{
"path": "tests/unit/order_of_ops.pn",
"chars": 123,
"preview": "# 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"
},
{
"path": "tests/unit/strings.pn",
"chars": 284,
"preview": "# Pinecone strings test\nprint: \"hello\\na\\nbxyz\\nwe\\n6\\n4\\n89.342\\ntru\\nfls\\nfls\\n_____\"\n\nmyStr: \"hello\"\nprint: myStr\npri"
},
{
"path": "tests/unit/type_info.pn",
"chars": 363,
"preview": "# tests various funcs that return info about types\n\nprint: \"String\\nInt\\n1\\n1\\n2\\n0\\n_____\"\n\nprint: \"hay\".typeName\n\nprin"
},
{
"path": "tests/unit/vars.pn",
"chars": 78,
"preview": "# 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",
"chars": 709,
"preview": "# 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\\nwad"
},
{
"path": "tests/unit/windows_line_endings.pn",
"chars": 74,
"preview": "# Pinecone Windows line endings test\r\nprint: \"good\n_____\"\r\n\r\nprint: \"good\""
},
{
"path": "tutorials/0_setting_up.md",
"chars": 999,
"preview": "# Setting up your environment\n\nDisclamer: these steps work on Linux, and usually on OSX. Windows is not yet supported. F"
},
{
"path": "tutorials/1_basic_concepts.md",
"chars": 4787,
"preview": "# Basic Concepts\n\nThe tutorials for most programming languages start with a hello world program, but Pinecone isn't most"
},
{
"path": "tutorials/2_control_flow.md",
"chars": 1518,
"preview": "# Control Flow\nIn Pinecone, control flow is done with symbols instead of keywords. There are two symbols used for contro"
},
{
"path": "tutorials/3_strings_and_input.md",
"chars": 1224,
"preview": "# Strings and Input\n\nIn Pinecone, like in many langauges, a string is a series of characters of any length. To make a st"
},
{
"path": "tutorials/4_structures_and_functions.md",
"chars": 2645,
"preview": "# Structures and Functions\n\n## Types\n\nSince types for variables are implicit, you usually don't have to specify them. Th"
},
{
"path": "tutorials/5_whatevs.md",
"chars": 1697,
"preview": "# Whatevs\n\n## The Problem\nSometimes explicitly declaring a type is inconvenient. You don't want a function to always tak"
},
{
"path": "tutorials/6_transpiling_to_cpp.md",
"chars": 2585,
"preview": "# Transpiling to C++\n\nUp until now you have been running your Pinecone code the default way, which is currently with the"
},
{
"path": "tutorials/7_temporary_hacks.md",
"chars": 3530,
"preview": "# Temporary Hacks\n\nPinecone is still under rapid development, and there are a lot of features that are not yet implement"
},
{
"path": "tutorials/index.md",
"chars": 406,
"preview": "# 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"
}
]
About this extraction
This page contains the full source code of the william01110111/Pinecone GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 111 files (324.4 KB), approximately 102.2k tokens, and a symbol index with 375 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.