mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Fixed some indexing bugs
This commit is contained in:
21
README.md
21
README.md
@@ -8,6 +8,15 @@ This is the Toy programming language interpreter, written in C.
|
||||
|
||||
Special thanks to http://craftinginterpreters.com/ for their fantastic book that set me on this path.
|
||||
|
||||
## Nifty Features
|
||||
|
||||
* Simple C-like syntax
|
||||
* Bytecode intermediate compilation
|
||||
* `import` and `export` variables from the host program
|
||||
* Optional, but robust type system
|
||||
* functions and types are first-class citizens
|
||||
* Fancy slice notation for strings, arrays and dictionaries (`print greeting[0:4:-1]; //prints "olleh"`)
|
||||
|
||||
## Building
|
||||
|
||||
Simply run make in the root directory.
|
||||
@@ -15,7 +24,7 @@ Simply run make in the root directory.
|
||||
## Syntax
|
||||
|
||||
```
|
||||
import "standard"; //for a bunch of utility functions
|
||||
import standard; //for a bunch of utility functions
|
||||
|
||||
|
||||
print "Hello world"; //"print" is a keyword
|
||||
@@ -36,13 +45,13 @@ fn makeCounter() { //declare a function like this
|
||||
return counter; //closures are explicitly supported
|
||||
}
|
||||
|
||||
var counter = makeCounter();
|
||||
var tally = makeCounter();
|
||||
|
||||
print counter(); //1
|
||||
print counter(); //2
|
||||
print counter(); //3
|
||||
print tally(); //1
|
||||
print tally(); //2
|
||||
print tally(); //3
|
||||
|
||||
export makeCounter; //export this variable to the host program
|
||||
export tally; //export this variable to the host program
|
||||
```
|
||||
|
||||
# License
|
||||
|
||||
@@ -2,14 +2,24 @@
|
||||
|
||||
|
||||
|
||||
var t: type = astype [int];
|
||||
var u: type = astype [t];
|
||||
fn makeCounter() {
|
||||
var total: int = 0;
|
||||
|
||||
var a: u;
|
||||
fn counter(): int {
|
||||
return ++total;
|
||||
}
|
||||
|
||||
t = astype [float]; //redefnition
|
||||
return counter;
|
||||
}
|
||||
|
||||
var b: u;
|
||||
var tally = makeCounter();
|
||||
|
||||
print typeof a; //<[<int>]>
|
||||
print typeof b; //<[<float>]>
|
||||
print tally(); //1
|
||||
print tally(); //2
|
||||
print tally(); //3
|
||||
|
||||
export tally;
|
||||
|
||||
//heck yeah!
|
||||
import tally as tally2;
|
||||
print tally2(); //4
|
||||
|
||||
@@ -1,8 +1,22 @@
|
||||
|
||||
//test basic indexing
|
||||
{
|
||||
var week = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"];
|
||||
|
||||
assert week[1] == "tuesday", "basic indexing failed (single element)";
|
||||
|
||||
assert week[1:1] == ["tuesday"], "basic indexing failed (single element as array)";
|
||||
|
||||
assert week[:] == ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"], "basic default indexing failed (first and second)";
|
||||
assert week[::] == ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"], "basic default indexing failed (first, second and third)";
|
||||
}
|
||||
|
||||
|
||||
//test basic replacement
|
||||
{
|
||||
var week = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"];
|
||||
|
||||
week[3] = "Holiday";
|
||||
week[3:3] = "Holiday";
|
||||
|
||||
assert week == ["monday", "tuesday", "wednesday", "Holiday", "friday", "saturday", "sunday"], "basic replacement failed";
|
||||
}
|
||||
|
||||
@@ -1,13 +1,24 @@
|
||||
//test basic replacement
|
||||
//test basic indexing
|
||||
var greeting: string = "hello world";
|
||||
|
||||
assert greeting[1] == "e", "basic default index failed (first)";
|
||||
|
||||
assert greeting[:] == "hello world", "basic default index failed (first and second)";
|
||||
|
||||
assert greeting[::] == "hello world", "basic default index failed (first, second & third)";
|
||||
|
||||
assert greeting[0:4] == "hello", "basic indexing failed";
|
||||
|
||||
|
||||
|
||||
//test basic replacement
|
||||
greeting[0:4] = "goodnight";
|
||||
|
||||
assert greeting == "goodnight world", "basic replacement failed";
|
||||
|
||||
|
||||
//test backwards string
|
||||
assert greeting[::-1] == "dlrow thgindoog", "backwards string failed";
|
||||
assert greeting[11:15:-1] == "dlrow", "backwards indexed string failed";
|
||||
|
||||
|
||||
//test string weird manipulation
|
||||
|
||||
@@ -1386,7 +1386,7 @@ static bool execIndex(Interpreter* interpreter) {
|
||||
freeLiteral(second);
|
||||
freeLiteral(first);
|
||||
freeLiteral(compound);
|
||||
freeLiteral(idn);
|
||||
//freeLiteral(idn); //since compound is freed, idn is still pointing there
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -329,7 +329,7 @@ int _index(Interpreter* interpreter, LiteralArray* arguments) {
|
||||
if (!IS_NULL(second)) {
|
||||
if (IS_BOOLEAN(second)) {
|
||||
freeLiteral(second);
|
||||
second = TO_INTEGER_LITERAL(AS_ARRAY(compound)->count);
|
||||
second = TO_INTEGER_LITERAL(AS_ARRAY(compound)->count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,10 +387,10 @@ int _index(Interpreter* interpreter, LiteralArray* arguments) {
|
||||
LiteralArray* result = ALLOCATE(LiteralArray, 1);
|
||||
initLiteralArray(result);
|
||||
|
||||
int min = AS_INTEGER(third) > 0 ? 0 : AS_INTEGER(second) - 1;
|
||||
int min = AS_INTEGER(third) > 0 ? AS_INTEGER(first) : AS_INTEGER(second);
|
||||
|
||||
//copy compound into result
|
||||
for (int i = min; i >= 0 && i <= AS_ARRAY(compound)->count && i >= AS_INTEGER(first) && i < AS_INTEGER(second); i += AS_INTEGER(third)) {
|
||||
for (int i = min; i >= 0 && i <= AS_ARRAY(compound)->count && i >= AS_INTEGER(first) && i <= AS_INTEGER(second); i += AS_INTEGER(third)) {
|
||||
Literal idx = TO_INTEGER_LITERAL(i);
|
||||
Literal tmp = getLiteralArray(AS_ARRAY(compound), idx);
|
||||
pushLiteralArray(result, tmp);
|
||||
@@ -417,7 +417,7 @@ int _index(Interpreter* interpreter, LiteralArray* arguments) {
|
||||
if (!IS_NULL(second)) {
|
||||
if (IS_BOOLEAN(second)) {
|
||||
freeLiteral(second);
|
||||
second = TO_INTEGER_LITERAL(AS_ARRAY(compound)->count);
|
||||
second = TO_INTEGER_LITERAL(AS_INTEGER(first));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -487,6 +487,7 @@ int _index(Interpreter* interpreter, LiteralArray* arguments) {
|
||||
|
||||
int min = AS_INTEGER(third) > 0 ? 0 : AS_ARRAY(assign)->count - 1;
|
||||
|
||||
if (IS_ARRAY(assign)) { //push elements of an assigned array
|
||||
for (int i = min; i >= 0 && i < AS_ARRAY(assign)->count; i += AS_INTEGER(third)) {
|
||||
Literal idx = TO_INTEGER_LITERAL(i);
|
||||
Literal tmp = getLiteralArray(AS_ARRAY(assign), idx); //backwards
|
||||
@@ -497,6 +498,10 @@ int _index(Interpreter* interpreter, LiteralArray* arguments) {
|
||||
freeLiteral(idx);
|
||||
freeLiteral(tmp);
|
||||
}
|
||||
}
|
||||
else { //push just one element into the array
|
||||
pushLiteralArray(result, assign);
|
||||
}
|
||||
|
||||
for (int i = AS_INTEGER(second) + 1; i < AS_ARRAY(compound)->count; i++) {
|
||||
Literal idx = TO_INTEGER_LITERAL(i);
|
||||
@@ -649,11 +654,12 @@ int _index(Interpreter* interpreter, LiteralArray* arguments) {
|
||||
//start building a new string from the old one
|
||||
char* result = ALLOCATE(char, MAX_STRING_LENGTH);
|
||||
|
||||
int min = AS_INTEGER(third) > 0 ? AS_INTEGER(first) : AS_INTEGER(second) - 1;
|
||||
int lower = AS_INTEGER(third) > 0 ? AS_INTEGER(first) : AS_INTEGER(first) -1;
|
||||
int min = AS_INTEGER(third) > 0 ? AS_INTEGER(first) : AS_INTEGER(second) -1;
|
||||
|
||||
//copy compound into result
|
||||
int resultIndex = 0;
|
||||
for (int i = min; i >= AS_INTEGER(first) && i < AS_INTEGER(second); i += AS_INTEGER(third)) {
|
||||
for (int i = min; i >= lower && i <= AS_INTEGER(second); i += AS_INTEGER(third)) {
|
||||
result[ resultIndex++ ] = AS_STRING(compound)[ i ];
|
||||
}
|
||||
|
||||
|
||||
@@ -736,17 +736,24 @@ static Opcode indexAccess(Parser* parser, Node** nodeHandle) {
|
||||
emitNodeLiteral(&second, TO_BOOLEAN_LITERAL(true));
|
||||
emitNodeLiteral(&third, TO_BOOLEAN_LITERAL(true));
|
||||
|
||||
bool readFirst = false; //pattern matching is bullcrap
|
||||
|
||||
//eat the first
|
||||
if (!match(parser, TOKEN_COLON)) {
|
||||
freeNode(first);
|
||||
parsePrecedence(parser, &first, PREC_TERNARY);
|
||||
match(parser, TOKEN_COLON);
|
||||
readFirst = true;
|
||||
}
|
||||
|
||||
if (match(parser, TOKEN_BRACKET_RIGHT)) {
|
||||
|
||||
if (readFirst) {
|
||||
freeNode(second);
|
||||
freeNode(third);
|
||||
second = NULL;
|
||||
}
|
||||
|
||||
freeNode(third);
|
||||
third = NULL;
|
||||
|
||||
emitNodeIndex(nodeHandle, first, second, third);
|
||||
|
||||
Reference in New Issue
Block a user