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
================================================
================================================
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+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>."
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=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 {Hashmap}:
(
size: 10
used: (IntArray: size)
i: 0 | i {Hashmap}:
(
used: (IntArray: size)
i: 0 | i {Int}: me.keys.len
String :: {Hashmap} -> {String}:
(
out: "hashmap:\n"
i: 0 | i {String}:
(
out: ""
i: 0 | i {String}:
(
out: ""
found: fls
i: 0 | i {Queue}: (
(IntArray: 1), 0, 0
)
resize :: {Int}: (
newArray: IntArray: in
i: 0 | i= 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 "+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
#include
#include
#include
#include "utils/stringDrawing.h"
#include // 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 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 inLeft, shared_ptr 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 Action;
class AstNodeBase;
//Action lambdaAction(Type returnTypeIn, function lambdaIn, Type inLeftTypeIn, Type inRightTypeIn, string textIn);
Action lambdaAction(Type inLeftTypeIn, Type inRightTypeIn, Type returnTypeIn, function lambdaIn, function addCppToProg, string textIn);
Action createNewVoidAction();
Action branchAction(Action leftInputIn, Action actionIn, Action rightInputIn);
Action functionAction(Action actionIn, shared_ptr stackFameIn);
Action functionAction(unique_ptr nodeIn, Type returnTypeIn, shared_ptr 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& actionsIn, const std::vector& destroyersIn);
Action loopAction(Action conditionIn, Action loopActionIn);
Action loopAction(Action conditionIn, Action endActionIn, Action loopActionIn);
Action makeTupleAction(const std::vector& 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 ns);
Action typeGetAction(Type typeIn);
================================================
FILE: h/AllOperators.h
================================================
#pragma once
#include
using std::vector;
#include
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& 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& 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 opsMap;
};
// the single instance of this class, starts out as nullptr but chages to a real instance in AllOperators::init
//extern shared_ptr ops;
extern AllOperators* ops;
================================================
FILE: h/AstNode.h
================================================
#pragma once
#include "Token.h"
#include "Action.h"
#include "ErrorHandler.h"
class NamespaceData;
typedef shared_ptr Namespace;
#include
using std::vector;
class AstNodeBase;
typedef unique_ptr AstNode;
AstNode astNodeFromTokens(const vector& 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 make() {return unique_ptr(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 make(vector& in)
{
unique_ptr 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 nodes;
};
class AstConstExpression;
class AstToken: public AstNodeBase
{
public:
static unique_ptr make(Token tokenIn)
{
unique_ptr 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 make(AstNode leftInIn, AstNode centerIn, AstNode rightInIn)
{
unique_ptr 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 make(unique_ptr centerIn, AstNode rightInIn)
{
unique_ptr 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*)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 center=nullptr;
AstNode rightIn=nullptr;
};
class AstOpWithInput: public AstNodeBase
{
public:
static unique_ptr make(vector& leftInIn, Token tokenIn, vector& rightInIn)
{
unique_ptr 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 leftIn, rightIn;
};
class AstTuple: public AstNodeBase
{
public:
// make a new instance of this type of node
static unique_ptr make(vector& in)
{
unique_ptr 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 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 make(Type typeIn)
{
unique_ptr 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 make()
{
unique_ptr 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 make(Token tokenIn)
{
unique_ptr 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 type;
};
static unique_ptr make(vector& in)
{
unique_ptr 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*)subTypes[i].type->makeCopy(copyCache).release())});
}
return AstNode(out);
}
void resolveReturnType();
Token getToken() {return subTypes.empty()?nullptr:subTypes[0].name;}
private:
vector subTypes;
};
class AstActionWrapper: public AstNodeBase
{
public:
static unique_ptr make(Action actionIn) {
auto out = unique_ptr(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 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 lambda;
};
================================================
FILE: h/CppProgram.h
================================================
#pragma once
#include "Type.h"
#include