Compare commits

..

8 Commits

Author SHA1 Message Date
Kayne Ruse b602e2ff87 Tweaked build trigger 2024-09-22 15:04:27 +10:00
Kayne Ruse 0b99eb7b0c Bumped patch version 2024-09-22 14:45:04 +10:00
Kayne Ruse 2505cedc79 Update README.md 2024-09-22 14:43:20 +10:00
Kayne Ruse d7035a59c8 Updated CI 2024-08-11 21:25:11 +10:00
Kayne Ruse ea584d8950 Fixed the failing build on mingw
Squashed commit of the following:

commit c48929d25a84331ca8bd1b27be2c6aa4f3b4db12
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Fri Aug 9 23:12:49 2024 +1000

    Update c-cpp.yml

    I'm only going a little bit nuts.

commit 3f65882bdc75f1712c9a3c9d2ddf0e53a27ce4b9
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Fri Aug 9 22:49:18 2024 +1000

    Update c-cpp.yml

    It would be great if this was documented better.

commit d3abeda7c2776bb2e82ca635cd659967afa6ad75
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Fri Aug 9 21:40:39 2024 +1000

    Bumped license date

commit 17bbce9d7ca212064bc95e467933c5602a89fb4c
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Fri Aug 9 21:33:57 2024 +1000

    Fixed the failing build on mingw

    There seems to be persistent issues with different compilers
    displaying the values of size_t, so I simply cast it to an integer.

commit 843a76d0ac44328776f8ecf83a66caa7ea7fdef6
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Fri Aug 9 21:17:17 2024 +1000

    Updated CI

commit 08cd89c58d8d028438b9f83a60f5dd9265cc3465
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Fri Aug 9 21:09:03 2024 +1000

    Why did that fail last time?
2024-08-09 23:25:56 +10:00
Kayne Ruse 2ce9a0cf42 Fixed an AST bug 2024-07-20 16:27:07 +10:00
Kayne Ruse b77f0fb50d Merge pull request #117 from hiperiondev/main
Add prefix in function for label code
2023-09-01 23:36:58 +10:00
hiperiondev edb5a52562 Add prefix in function for label code 2023-08-29 22:41:52 -03:00
22 changed files with 70 additions and 1213 deletions
@@ -1,17 +1,26 @@
name: Comprehensive Tests
name: Continuous Integration v1.x
#trigger when these occur
on:
push:
branches: [ "main", "*" ]
branches:
- v1
pull_request:
branches: [ "main" ]
types:
- opened
- edited
- reopened
branches:
- v1
workflow_dispatch:
#testing the CI workflows under multiple supported conditions
jobs:
test-valgrind:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: install valgrind
run: sudo apt install valgrind
- name: make test (valgrind)
@@ -21,7 +30,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: make test (sanitized)
run: make test-sanitized
@@ -29,6 +38,6 @@ jobs:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: make test (mingw32)
run: make test
+1 -1
View File
@@ -1,6 +1,6 @@
# License
Copyright (c) 2020-2023 Kayne Ruse, KR Game Studios
Copyright (c) 2020-2024 Kayne Ruse, KR Game Studios
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
+2 -2
View File
@@ -2,7 +2,7 @@
<image src="toylogo.png" />
</p>
# Toy
# Toy v1
The Toy programming language is an imperative bytecode-intermediate embedded scripting language. It isn't intended to operate on its own, but rather as part of another program, the "host". This process is intended to allow a decent amount of easy customisation by the host's end user, by exposing logic in script files. Alternatively, binary files in a custom format can be used as well.
@@ -83,4 +83,4 @@ Unnamed Individuals - Feedback
* Seth A. Robinson
Special thanks to http://craftinginterpreters.com/ for their fantastic book that set me on this path.
Special thanks to http://craftinginterpreters.com/ for their fantastic book that set me on this path.
-940
View File
@@ -1,940 +0,0 @@
#include "lib_fileio.h"
#include "toy_memory.h"
#include "drive_system.h"
#include <limits.h>
#include <stdio.h>
typedef struct Toy_File
{
FILE* fp;
Toy_RefString* mode;
Toy_RefString* path;
} Toy_File;
Toy_File* createToyFile(Toy_RefString* mode, Toy_RefString* path) {
Toy_File* file = TOY_ALLOCATE(Toy_File, 1);
file->fp = NULL;
file->mode = Toy_copyRefString(mode);
file->path = Toy_copyRefString(path);
return file;
}
void deleteToyFile(Toy_File* file) {
Toy_deleteRefString(file->mode);
Toy_deleteRefString(file->path);
TOY_FREE(Toy_File, file);
}
static int nativeOpen(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count < 1) {
interpreter->errorOutput("Too few arguments open(string, string) expects two arguments\n");
return -1;
}
else if (arguments->count > 2) {
interpreter->errorOutput("Too many arguments open(string, string) expects two arguments\n");
return -1;
}
Toy_Literal modeLiteral = arguments->count == 2? Toy_popLiteralArray(arguments) : TOY_TO_STRING_LITERAL(Toy_createRefString("r"));
Toy_Literal drivePathLiteral = Toy_popLiteralArray(arguments);
// parse the drivePath (if it's an identifier)
Toy_Literal drivePathLiteralIdn = drivePathLiteral;
if (TOY_IS_IDENTIFIER(drivePathLiteral) && Toy_parseIdentifierToValue(interpreter, &drivePathLiteral)) {
Toy_freeLiteral(drivePathLiteralIdn);
}
// check the drivePath type
if (!TOY_IS_STRING(drivePathLiteral)) {
interpreter->errorOutput("Incorrect argument type expected a string as the first argument to open(string, string)\n");
Toy_freeLiteral(drivePathLiteral);
Toy_freeLiteral(modeLiteral);
return -1;
}
Toy_Literal filePathLiteral = Toy_getDrivePathLiteral(interpreter, &drivePathLiteral);
if (TOY_IS_NULL(filePathLiteral)) {
interpreter->errorOutput("File not found in the specified drive\n");
Toy_freeLiteral(drivePathLiteral);
Toy_freeLiteral(filePathLiteral);
Toy_freeLiteral(modeLiteral);
return -1;
}
// parse the mode (if it's an identifier)
Toy_Literal modeLiteralIdn = modeLiteral;
if (TOY_IS_IDENTIFIER(modeLiteral) && Toy_parseIdentifierToValue(interpreter, &modeLiteral)) {
Toy_freeLiteral(modeLiteralIdn);
}
// check the mode type
if (!TOY_IS_STRING(modeLiteral)) {
interpreter->errorOutput("Incorrect argument type expected a string as the second argument to open(string, string)\n");
Toy_freeLiteral(drivePathLiteral);
Toy_freeLiteral(filePathLiteral);
Toy_freeLiteral(modeLiteral);
return -1;
}
const char* filePath = Toy_toCString(TOY_AS_STRING(filePathLiteral));
size_t filePathLength = Toy_lengthRefString(TOY_AS_STRING(filePathLiteral));
const char* mode = Toy_toCString(TOY_AS_STRING(modeLiteral));
// build file object
Toy_File* file = createToyFile(TOY_AS_STRING(modeLiteral), TOY_AS_STRING(filePathLiteral));
// attempt to open file
file->fp = fopen(filePath, mode);
// result
Toy_Literal fileLiteral = TOY_TO_NULL_LITERAL;
if (file->fp == NULL) {
deleteToyFile(file);
}
else {
fileLiteral = TOY_TO_OPAQUE_LITERAL(file, TOY_OPAQUE_TAG_FILE);
}
Toy_pushLiteralArray(&interpreter->stack, fileLiteral);
// cleanup
Toy_freeLiteral(fileLiteral);
Toy_freeLiteral(drivePathLiteral);
Toy_freeLiteral(filePathLiteral);
Toy_freeLiteral(modeLiteral);
return 1;
}
static int nativeClose(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count != 1) {
interpreter->errorOutput("Too many arguments close() expects zero arguments\n");
return -1;
}
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
// parse the self (if it's an identifier)
Toy_Literal selfLiteralIdn = selfLiteral;
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
Toy_freeLiteral(selfLiteralIdn);
}
// check self type
if (!TOY_IS_OPAQUE(selfLiteral) && TOY_GET_OPAQUE_TAG(selfLiteral) != TOY_OPAQUE_TAG_FILE) {
interpreter->errorOutput("Incorrect self type close() expects a file type\n");
Toy_freeLiteral(selfLiteral);
return -1;
}
Toy_File* file = (Toy_File*)TOY_AS_OPAQUE(selfLiteral);
int result = 0;
if (
file->fp != stdout &&
file->fp != stdin &&
file->fp != NULL
) {
result = fclose(file->fp);
file->fp = NULL;
}
// return the result
Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(result != EOF);
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
// cleanup
deleteToyFile(file);
Toy_freeLiteral(resultLiteral);
Toy_freeLiteral(selfLiteral);
return 1;
}
static int nativeRead(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count < 2) {
interpreter->errorOutput("Too few arguments read(type) expects one argument\n");
return -1;
}
else if (arguments->count > 2) {
interpreter->errorOutput("Too many arguments read(type) expects one argument\n");
return -1;
}
Toy_Literal typeLiteral = Toy_popLiteralArray(arguments);
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
// parse the type (if it's an identifier)
Toy_Literal typeLiteralIdn = typeLiteral;
if (TOY_IS_IDENTIFIER(typeLiteral) && Toy_parseIdentifierToValue(interpreter, &typeLiteral)) {
Toy_freeLiteral(typeLiteralIdn);
}
// check the type type
if (!TOY_IS_TYPE(typeLiteral)) {
interpreter->errorOutput("Incorrect argument type expected a type as the first argument to read(type)\n");
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(typeLiteral);
return -1;
}
// parse the self (if it's an identifier)
Toy_Literal selfLiteralIdn = selfLiteral;
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
Toy_freeLiteral(selfLiteralIdn);
}
// check self type
if (!TOY_IS_OPAQUE(selfLiteral) && TOY_GET_OPAQUE_TAG(selfLiteral) != TOY_OPAQUE_TAG_FILE) {
interpreter->errorOutput("Incorrect self type, read(type) expects a file type\n");
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(typeLiteral);
return -1;
}
Toy_File* file = (Toy_File*)TOY_AS_OPAQUE(selfLiteral);
Toy_Literal resultLiteral = TOY_TO_NULL_LITERAL;
int error = 0;
switch (TOY_AS_TYPE(typeLiteral).typeOf) {
case TOY_LITERAL_BOOLEAN: {
char value = '0';
error = fscanf(file->fp, "%c", &value);
resultLiteral = TOY_TO_BOOLEAN_LITERAL(value != '0');
break;
}
case TOY_LITERAL_INTEGER: {
int value = 0;
error = fscanf(file->fp, "%i", &value);
resultLiteral = TOY_TO_INTEGER_LITERAL(value);
break;
}
case TOY_LITERAL_FLOAT: {
float value = 0.0f;
error = fscanf(file->fp, "%f", &value);
resultLiteral = TOY_TO_FLOAT_LITERAL(value);
break;
}
case TOY_LITERAL_STRING: { //BUG: needs a terminator to show how much to read
char value[TOY_MAX_STRING_LENGTH] = {0};
size_t size = fread(value, sizeof(char), TOY_MAX_STRING_LENGTH - 1, file->fp);
value[size] = '\0';
resultLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString(value));
break;
}
default: {
// TODO handle other types
break;
}
}
if (error != EOF) {
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
}
else {
Toy_pushLiteralArray(&interpreter->stack, TOY_TO_NULL_LITERAL);
}
// cleanup
Toy_freeLiteral(resultLiteral);
Toy_freeLiteral(typeLiteral);
Toy_freeLiteral(selfLiteral);
return 1;
}
static int nativeWrite(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count < 2) {
interpreter->errorOutput("Too few arguments write(any) expects one argument\n");
return -1;
}
else if (arguments->count > 2) {
interpreter->errorOutput("Too many arguments write(any) expects one argument\n");
return -1;
}
Toy_Literal valueLiteral = Toy_popLiteralArray(arguments);
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
// parse the value (if it's an identifier)
Toy_Literal valueLiteralIdn = valueLiteral;
if (TOY_IS_IDENTIFIER(valueLiteral) && Toy_parseIdentifierToValue(interpreter, &valueLiteral)) {
Toy_freeLiteral(valueLiteralIdn);
}
// check the value type
if (TOY_IS_NULL(valueLiteral)) {
interpreter->errorOutput("Incorrect argument type expected non null value as the first argument to write(any)\n");
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(valueLiteral);
return -1;
}
// parse the self (if it's an identifier)
Toy_Literal selfLiteralIdn = selfLiteral;
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
Toy_freeLiteral(selfLiteralIdn);
}
// check self type
if (!TOY_IS_OPAQUE(selfLiteral) && TOY_GET_OPAQUE_TAG(selfLiteral) != TOY_OPAQUE_TAG_FILE) {
interpreter->errorOutput("Incorrect self type write(any) expects a file type\n");
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(valueLiteral);
return -1;
}
Toy_File* file = (Toy_File*)TOY_AS_OPAQUE(selfLiteral);
int result = 0;
switch (valueLiteral.type) {
case TOY_LITERAL_BOOLEAN: {
result = fprintf(file->fp, "%i", TOY_AS_BOOLEAN(valueLiteral));
break;
}
case TOY_LITERAL_INTEGER: {
result = fprintf(file->fp, "%i", TOY_AS_INTEGER(valueLiteral));
break;
}
case TOY_LITERAL_FLOAT: {
result = fprintf(file->fp, "%f", TOY_AS_FLOAT(valueLiteral));
break;
}
case TOY_LITERAL_STRING: {
result = fprintf(file->fp, "%s", Toy_toCString(TOY_AS_STRING(valueLiteral)));
break;
}
default: {
// TODO handle other types
break;
}
}
Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(result > 0);
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
// cleanup
Toy_freeLiteral(resultLiteral);
Toy_freeLiteral(valueLiteral);
Toy_freeLiteral(selfLiteral);
return 1;
}
static int nativeRename(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count < 2) {
interpreter->errorOutput("Too few arguments rename(string) expects one argument\n");
return -1;
}
else if (arguments->count > 2) {
interpreter->errorOutput("Too many arguments rename(string) expects one argument\n");
return -1;
}
Toy_Literal valueLiteral = Toy_popLiteralArray(arguments);
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
// parse the value (if it's an identifier)
Toy_Literal valueLiteralIdn = valueLiteral;
if (TOY_IS_IDENTIFIER(valueLiteral) && Toy_parseIdentifierToValue(interpreter, &valueLiteral)) {
Toy_freeLiteral(valueLiteralIdn);
}
// check the value type
if (!TOY_IS_STRING(valueLiteral)) {
interpreter->errorOutput("Incorrect argument type expected a string as the first argument to rename(string)\n");
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(valueLiteral);
return -1;
}
// parse the self (if it's an identifier)
Toy_Literal selfLiteralIdn = selfLiteral;
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
Toy_freeLiteral(selfLiteralIdn);
}
// check self type
if (!TOY_IS_OPAQUE(selfLiteral) && TOY_GET_OPAQUE_TAG(selfLiteral) != TOY_OPAQUE_TAG_FILE) {
interpreter->errorOutput("Incorrect self type, rename(string) expects a file type\n");
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(valueLiteral);
return -1;
}
Toy_Literal filePathLiteral = Toy_getDrivePathLiteral(interpreter, &valueLiteral);
Toy_File* file = (Toy_File*)TOY_AS_OPAQUE(selfLiteral);
const char* newName = Toy_toCString(TOY_AS_STRING(filePathLiteral));
// close the file
if (file->fp != NULL) {
fclose(file->fp);
file->fp = NULL;
}
// rename the file
int result = rename(Toy_toCString(file->path), newName);
// open file again
file->fp = fopen(newName, Toy_toCString(file->mode));
// update the file object's name
Toy_deleteRefString(file->path);
file->path = Toy_createRefString(newName);
// return result
Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(result == 0);
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
// cleanup
Toy_freeLiteral(resultLiteral);
Toy_freeLiteral(filePathLiteral);
Toy_freeLiteral(valueLiteral);
Toy_freeLiteral(selfLiteral);
return 1;
}
static int nativeSeek(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count < 3) {
interpreter->errorOutput("Too few arguments seek(string, int) expects two arguments\n");
return -1;
}
else if (arguments->count > 3) {
interpreter->errorOutput("Too many arguments seek(string, int) expects two arguments\n");
return -1;
}
Toy_Literal offsetLiteral = Toy_popLiteralArray(arguments);
Toy_Literal originLiteral = Toy_popLiteralArray(arguments);
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
// parse the origin (if it's an identifier)
Toy_Literal originLiteralIdn = originLiteral;
if (TOY_IS_IDENTIFIER(originLiteral) && Toy_parseIdentifierToValue(interpreter, &originLiteral)) {
Toy_freeLiteral(originLiteralIdn);
}
// check the origin type
if (!TOY_IS_STRING(originLiteral)) {
interpreter->errorOutput("Incorrect argument type expected a string as the first argument to seek(string, int)\n");
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(offsetLiteral);
Toy_freeLiteral(originLiteral);
return -1;
}
// parse the offset (if it's an identifier)
Toy_Literal offsetLiteralIdn = offsetLiteral;
if (TOY_IS_IDENTIFIER(offsetLiteral) && Toy_parseIdentifierToValue(interpreter, &offsetLiteral)) {
Toy_freeLiteral(offsetLiteralIdn);
}
// check the offset type
if (!TOY_IS_INTEGER(offsetLiteral)) {
interpreter->errorOutput("Incorrect argument type expected a int as the second argument to seek(string, int)\n");
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(offsetLiteral);
Toy_freeLiteral(originLiteral);
return -1;
}
// parse the self (if it's an identifier)
Toy_Literal selfLiteralIdn = selfLiteral;
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
Toy_freeLiteral(selfLiteralIdn);
}
// check self type
if (!TOY_IS_OPAQUE(selfLiteral) && TOY_GET_OPAQUE_TAG(selfLiteral) != TOY_OPAQUE_TAG_FILE) {
interpreter->errorOutput("Incorrect self type seek(string, int) expects a file type\n");
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(offsetLiteral);
Toy_freeLiteral(originLiteral);
return -1;
}
Toy_File* file = (Toy_File*)TOY_AS_OPAQUE(selfLiteral);
Toy_RefString* orginString = TOY_AS_STRING(originLiteral);
int offset = TOY_AS_INTEGER(offsetLiteral);
int origin = -1;
if (Toy_equalsRefStringCString(orginString, "bgn")) {
origin = SEEK_SET;
}
else if (Toy_equalsRefStringCString(orginString, "cur")) {
origin = SEEK_CUR;
}
else if (Toy_equalsRefStringCString(orginString, "end")) {
origin = SEEK_END;
}
int result = origin >= SEEK_SET && origin <= SEEK_END?
fseek(file->fp, offset, origin) : -1;
Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(result == 0);
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
// cleanup
Toy_freeLiteral(resultLiteral);
Toy_freeLiteral(originLiteral);
Toy_freeLiteral(offsetLiteral);
Toy_freeLiteral(selfLiteral);
return 1;
}
static int nativeError(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count != 1) {
interpreter->errorOutput("Too many arguments error() expects zero arguments\n");
return -1;
}
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
// parse the self (if it's an identifier)
Toy_Literal selfLiteralIdn = selfLiteral;
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
Toy_freeLiteral(selfLiteralIdn);
}
// check self type
if (!TOY_IS_OPAQUE(selfLiteral) && TOY_GET_OPAQUE_TAG(selfLiteral) != TOY_OPAQUE_TAG_FILE) {
interpreter->errorOutput("Incorrect self type error() expects a file type\n");
Toy_freeLiteral(selfLiteral);
return -1;
}
Toy_File* file = (Toy_File*)TOY_AS_OPAQUE(selfLiteral);
int result = ferror(file->fp);
// return the result
Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(result != 0);
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
// cleanup
Toy_freeLiteral(selfLiteral);
return 1;
}
static int nativeCompleted(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count != 1) {
interpreter->errorOutput("Too many arguments completed() expects zero arguments\n");
return -1;
}
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
// parse the self (if it's an identifier)
Toy_Literal selfLiteralIdn = selfLiteral;
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
Toy_freeLiteral(selfLiteralIdn);
}
// check self type
if (!TOY_IS_OPAQUE(selfLiteral) && TOY_GET_OPAQUE_TAG(selfLiteral) != TOY_OPAQUE_TAG_FILE) {
interpreter->errorOutput("Incorrect self type completed() expects a file type\n");
Toy_freeLiteral(selfLiteral);
return -1;
}
Toy_File* file = (Toy_File*)TOY_AS_OPAQUE(selfLiteral);
int result = feof(file->fp);
// return the result
Toy_Literal resultLiteral = TOY_TO_BOOLEAN_LITERAL(result != 0);
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
// cleanup
Toy_freeLiteral(resultLiteral);
Toy_freeLiteral(selfLiteral);
return 1;
}
static int nativePosition(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count != 1) {
interpreter->errorOutput("Too many arguments position() expects zero arguments\n");
return -1;
}
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
// parse the self (if it's an identifier)
Toy_Literal selfLiteralIdn = selfLiteral;
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
Toy_freeLiteral(selfLiteralIdn);
}
// check self type
if (!TOY_IS_OPAQUE(selfLiteral) && TOY_GET_OPAQUE_TAG(selfLiteral) != TOY_OPAQUE_TAG_FILE) {
interpreter->errorOutput("Incorrect self type position() expects a file type\n");
Toy_freeLiteral(selfLiteral);
return -1;
}
Toy_File* file = (Toy_File*)TOY_AS_OPAQUE(selfLiteral);
// pervent integer overflow as ftell returns a long
int size = ftell(file->fp) > INT_MAX? INT_MAX : ftell(file->fp);
// return the result
Toy_Literal resultLiteral = TOY_TO_INTEGER_LITERAL(size);
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
// cleanup
Toy_freeLiteral(resultLiteral);
Toy_freeLiteral(selfLiteral);
return 1;
}
static int nativeSize(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count != 1) {
interpreter->errorOutput("Too many arguments size() expects zero arguments\n");
return -1;
}
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
// parse the self (if it's an identifier)
Toy_Literal selfLiteralIdn = selfLiteral;
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
Toy_freeLiteral(selfLiteralIdn);
}
// check self type
if (!TOY_IS_OPAQUE(selfLiteral) && TOY_GET_OPAQUE_TAG(selfLiteral) != TOY_OPAQUE_TAG_FILE) {
interpreter->errorOutput("Incorrect self type size() expects a file type\n");
Toy_freeLiteral(selfLiteral);
return -1;
}
Toy_File* file = (Toy_File*)TOY_AS_OPAQUE(selfLiteral);
int size = 0;
fseek(file->fp, 0, SEEK_END);
// pervent integer overflow as ftell returns a long
if (ftell(file->fp) > INT_MAX) {
size = INT_MAX;
}
else {
size = ftell(file->fp);
}
fseek(file->fp, 0, SEEK_SET);
// return the result
Toy_Literal resultLiteral = TOY_TO_INTEGER_LITERAL(size);
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
// cleanup
Toy_freeLiteral(resultLiteral);
Toy_freeLiteral(selfLiteral);
return 1;
}
static int nativeMode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count != 1) {
interpreter->errorOutput("Too many arguments mode() expects zero arguments\n");
return -1;
}
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
// parse the self (if it's an identifier)
Toy_Literal selfLiteralIdn = selfLiteral;
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
Toy_freeLiteral(selfLiteralIdn);
}
// check self type
if (!TOY_IS_OPAQUE(selfLiteral) && TOY_GET_OPAQUE_TAG(selfLiteral) != TOY_OPAQUE_TAG_FILE) {
interpreter->errorOutput("Incorrect self type mode() expects a file type\n");
Toy_freeLiteral(selfLiteral);
return -1;
}
Toy_File* file = (Toy_File*)TOY_AS_OPAQUE(selfLiteral);
// return the result
Toy_Literal resultLiteral = TOY_TO_STRING_LITERAL(Toy_copyRefString(file->mode));
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
// cleanup
Toy_freeLiteral(resultLiteral);
Toy_freeLiteral(selfLiteral);
return 1;
}
static int nativePath(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count != 1) {
interpreter->errorOutput("Too many arguments path() expects zero arguments\n");
return -1;
}
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
// parse the self (if it's an identifier)
Toy_Literal selfLiteralIdn = selfLiteral;
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
Toy_freeLiteral(selfLiteralIdn);
}
// check self type
if (!TOY_IS_OPAQUE(selfLiteral) && TOY_GET_OPAQUE_TAG(selfLiteral) != TOY_OPAQUE_TAG_FILE) {
interpreter->errorOutput("Incorrect self type path() expects a file type\n");
Toy_freeLiteral(selfLiteral);
return -1;
}
Toy_File* file = (Toy_File*)TOY_AS_OPAQUE(selfLiteral);
// return the result
Toy_Literal resultLiteral = TOY_TO_STRING_LITERAL(Toy_copyRefString(file->path));
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
// cleanup
Toy_freeLiteral(resultLiteral);
Toy_freeLiteral(selfLiteral);
return 1;
}
// call the hook
typedef struct Natives {
char* name;
Toy_NativeFn fn;
} Natives;
typedef struct Variable {
Toy_Literal key;
Toy_Literal identifier;
Toy_Literal literal;
} Variable;
// Helper function create a int variable
void createToyVariableInt(Variable* variable, char* key, int literal) {
variable->key = TOY_TO_STRING_LITERAL(Toy_createRefString(key));
variable->identifier = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString(key));
variable->literal = TOY_TO_INTEGER_LITERAL(literal);
}
// Helper function create a file variable
void createToyVariableFile(Variable* variable, char* key, Toy_File* literal) {
variable->key = TOY_TO_STRING_LITERAL(Toy_createRefString(key));
variable->identifier = TOY_TO_IDENTIFIER_LITERAL(Toy_createRefString(key));
variable->literal = TOY_TO_OPAQUE_LITERAL(literal, TOY_OPAQUE_TAG_FILE);
}
// Helper function to clean up variables
void deleteToyVariables(Variable variables[], int size) {
for (int i = 0; i < size; i++) {
Toy_freeLiteral(variables[i].key);
Toy_freeLiteral(variables[i].identifier);
Toy_freeLiteral(variables[i].literal);
}
}
// Helper to check for naming conflicts with existing variables
bool scopeConflict(Toy_Interpreter* interpreter, Variable variables[], int size) {
for (int i = 0; i < size; i++) {
if (Toy_isDeclaredScopeVariable(interpreter->scope, variables[i].literal)) {
interpreter->errorOutput("Can't override an existing variable\n");
deleteToyVariables(variables, size);
return true;
}
}
return false;
}
// Helper to place variables into scope should be called after scopeConflict
void exposeVariablesToScope(Toy_Interpreter* interpreter, Variable variables[], int size) {
Toy_Literal intType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_INTEGER, false);
Toy_Literal opaqueType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_OPAQUE, false);
for (int i = 0; i < size; i++) {
if (TOY_IS_INTEGER(variables[i].literal)) {
Toy_declareScopeVariable(interpreter->scope, variables[i].identifier, intType);
}
else if (TOY_IS_OPAQUE(variables[i].literal)) {
Toy_declareScopeVariable(interpreter->scope, variables[i].identifier, opaqueType);
}
Toy_setScopeVariable(interpreter->scope, variables[i].identifier, variables[i].literal, true);
}
Toy_freeLiteral(intType);
Toy_freeLiteral(opaqueType);
}
int Toy_hookFileIO(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
// build the natives list
Natives natives[] = {
// access
{"open", nativeOpen},
{"close", nativeClose},
// operations
{"read", nativeRead},
{"write", nativeWrite},
{"rename", nativeRename},
{"seek", nativeSeek},
// accessors
{"error", nativeError},
{"completed", nativeCompleted},
{"position", nativePosition},
{"size", nativeSize},
{"mode", nativeMode},
{"path", nativePath},
{NULL, NULL}
};
// global variables
const int VARIABLES_SIZE = 5;
Variable variables[VARIABLES_SIZE];
createToyVariableInt(&variables[0], "MAX_FILENAME_SIZE", FILENAME_MAX);
createToyVariableInt(&variables[1], "MAX_FILES_OPEN", FOPEN_MAX);
createToyVariableInt(&variables[2], "END_OF_FILE", EOF);
Toy_RefString* outMode = Toy_createRefString("w");
Toy_RefString* outName = Toy_createRefString("output");
static Toy_File* outFile;
outFile = createToyFile(outMode, outName);
outFile->fp = stdout;
createToyVariableFile(&variables[3], "output", outFile);
Toy_deleteRefString(outMode);
Toy_deleteRefString(outName);
Toy_RefString* inMode = Toy_createRefString("r");
Toy_RefString* inName = Toy_createRefString("input");
static Toy_File* inFile;
inFile = createToyFile(inMode, inName);
inFile->fp = stdin;
createToyVariableFile(&variables[4], "input", inFile);
Toy_deleteRefString(inMode);
Toy_deleteRefString(inName);
// store the library in an aliased dictionary
if (!TOY_IS_NULL(alias)) {
// make sure the name isn't taken
if (Toy_isDeclaredScopeVariable(interpreter->scope, alias)) {
interpreter->errorOutput("Can't override an existing variable\n");
Toy_freeLiteral(alias);
return -1;
}
// create the dictionary to load up with functions
Toy_LiteralDictionary* dictionary = TOY_ALLOCATE(Toy_LiteralDictionary, 1);
Toy_initLiteralDictionary(dictionary);
// load the dict with functions
for (int i = 0; natives[i].name; i++) {
Toy_Literal name = TOY_TO_STRING_LITERAL(Toy_createRefString(natives[i].name));
Toy_Literal func = TOY_TO_FUNCTION_NATIVE_LITERAL(natives[i].fn);
Toy_setLiteralDictionary(dictionary, name, func);
Toy_freeLiteral(name);
Toy_freeLiteral(func);
}
// set global variables
for (int i = 0; i < VARIABLES_SIZE; i++) {
Toy_setLiteralDictionary(dictionary, variables[i].key, variables[i].literal);
}
// build the type
Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true);
Toy_Literal anyType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_ANY, true);
Toy_Literal fnType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_FUNCTION_NATIVE, true);
TOY_TYPE_PUSH_SUBTYPE(&type, anyType);
TOY_TYPE_PUSH_SUBTYPE(&type, fnType);
// set scope
Toy_Literal dict = TOY_TO_DICTIONARY_LITERAL(dictionary);
Toy_declareScopeVariable(interpreter->scope, alias, type);
Toy_setScopeVariable(interpreter->scope, alias, dict, false);
// cleanup
Toy_freeLiteral(dict);
Toy_freeLiteral(type);
return 0;
}
// default
for (int i = 0; natives[i].name; i++) {
Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn);
}
if (scopeConflict(interpreter, variables, VARIABLES_SIZE)) {
return -1;
}
exposeVariablesToScope(interpreter, variables, VARIABLES_SIZE);
deleteToyVariables(variables, VARIABLES_SIZE);
return 0;
}
-7
View File
@@ -1,7 +0,0 @@
#pragma once
#include "toy_interpreter.h"
#define TOY_OPAQUE_TAG_FILE 300
int Toy_hookFileIO(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias);
+3 -3
View File
@@ -661,7 +661,7 @@ static int nativeConcat(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
}
//get the combined length for the new string
size_t length = TOY_AS_STRING(selfLiteral)->length + TOY_AS_STRING(otherLiteral)->length + 1;
size_t length = TOY_AS_STRING(selfLiteral)->length + TOY_AS_STRING(otherLiteral)->length;
if (length > TOY_MAX_STRING_LENGTH) {
interpreter->errorOutput("Can't concatenate these strings, result is too long (error found in concat)\n");
@@ -671,8 +671,8 @@ static int nativeConcat(Toy_Interpreter* interpreter, Toy_LiteralArray* argument
}
//allocate the space and generate
char* buffer = TOY_ALLOCATE(char, length);
snprintf(buffer, length, "%s%s", Toy_toCString(TOY_AS_STRING(selfLiteral)), Toy_toCString(TOY_AS_STRING(otherLiteral)));
char* buffer = TOY_ALLOCATE(char, length + 1);
snprintf(buffer, length + 1, "%s%s", Toy_toCString(TOY_AS_STRING(selfLiteral)), Toy_toCString(TOY_AS_STRING(otherLiteral)));
Toy_Literal result = TOY_TO_STRING_LITERAL(Toy_createRefString(buffer));
-2
View File
@@ -4,7 +4,6 @@
#include "lib_standard.h"
#include "lib_random.h"
#include "lib_runner.h"
#include "lib_fileio.h"
#include "lib_math.h"
#include "toy_console_colors.h"
@@ -32,7 +31,6 @@ void repl(const char* initialInput) {
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
Toy_injectNativeHook(&interpreter, "random", Toy_hookRandom);
Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner);
Toy_injectNativeHook(&interpreter, "fileio", Toy_hookFileIO);
Toy_injectNativeHook(&interpreter, "math", Toy_hookMath);
for(;;) {
-2
View File
@@ -3,7 +3,6 @@
#include "lib_standard.h"
#include "lib_random.h"
#include "lib_runner.h"
#include "lib_fileio.h"
#include "lib_math.h"
#include "toy_console_colors.h"
@@ -117,7 +116,6 @@ void Toy_runBinary(const unsigned char* tb, size_t size) {
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
Toy_injectNativeHook(&interpreter, "random", Toy_hookRandom);
Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner);
Toy_injectNativeHook(&interpreter, "fileio", Toy_hookFileIO);
Toy_injectNativeHook(&interpreter, "math", Toy_hookMath);
Toy_runInterpreter(&interpreter, tb, (int)size);
-61
View File
@@ -1,61 +0,0 @@
import math;
import fileio;
import standard;
fn circle(radius: int, centerX: int, centerY: int) {
for (var y: int = 0; y <= 2 * radius; y++) {
for (var x: int = 0; x <= 2 * radius; x++) {
var distance: int = round(sqrt((x - radius) * (x - radius) + (y - radius) * (y - radius)));
if (distance <= radius) {
output.write("*");
} else {
output.write(" ");
}
}
output.write("\n");
}
}
fn triangle(height: int) {
for (var i: int = 1; i <= height; i++) {
for (var j: int = 1; j <= height - i; j++) {
output.write(" ");
}
for (var j: int = 1; j <= 2 * i - 1; j++) {
output.write("*");
}
output.write("\n");
}
}
fn square(size: int) {
for (var i: int = 0; i < size; ++i) {
for (var j: int = 0; j < size; ++j) {
output.write("* ");
}
output.write("\n");
}
}
while (true) {
output.write("Enter:\n0\tfor circle\n1\tfor triangle\n2\tfor square\n> ");
var result: any = input.read(int);
if (result == 0) {
circle(2, 5, 5);
}
else if (result == 1) {
triangle(5);
}
else if (result == 2) {
square(5);
}
else {
output.write("invalid input :(\n");
}
}
+4 -4
View File
@@ -362,8 +362,8 @@ void Toy_emitASTNodeAnd(Toy_ASTNode** nodeHandle, Toy_ASTNode* rhs) {
Toy_ASTNode* tmp = TOY_ALLOCATE(Toy_ASTNode, 1);
tmp->type = TOY_AST_NODE_AND;
tmp->binary.left = *nodeHandle;
tmp->binary.right = rhs;
tmp->pathAnd.left = *nodeHandle;
tmp->pathAnd.right = rhs;
*nodeHandle = tmp;
}
@@ -372,8 +372,8 @@ void Toy_emitASTNodeOr(Toy_ASTNode** nodeHandle, Toy_ASTNode* rhs) {
Toy_ASTNode* tmp = TOY_ALLOCATE(Toy_ASTNode, 1);
tmp->type = TOY_AST_NODE_OR;
tmp->binary.left = *nodeHandle;
tmp->binary.right = rhs;
tmp->pathOr.left = *nodeHandle;
tmp->pathOr.right = rhs;
*nodeHandle = tmp;
}
+1 -1
View File
@@ -64,7 +64,7 @@ The current patch version of Toy. This value is embedded into the bytecode.
This value MUST fit into an unsigned char.
!*/
#define TOY_VERSION_PATCH 1
#define TOY_VERSION_PATCH 2
/*!
### TOY_VERSION_BUILD
+2 -2
View File
@@ -455,8 +455,8 @@ static void printToBuffer(const char* str) {
globalPrintBuffer = TOY_GROW_ARRAY(char, globalPrintBuffer, oldCapacity, globalPrintCapacity);
}
snprintf(globalPrintBuffer + globalPrintCount, strlen(str) + 1, "%s", str ? str : "\0");
globalPrintCount += strlen(str);
size_t total = snprintf(globalPrintBuffer + globalPrintCount, strlen(str) + 1, "%s", str ? str : "\0");
globalPrintCount += total;
}
//exposed functions
+1 -1
View File
@@ -22,7 +22,7 @@ void* Toy_private_defaultMemoryAllocator(void* pointer, size_t oldSize, size_t n
void* mem = realloc(pointer, newSize);
if (mem == NULL) {
fprintf(stderr, TOY_CC_ERROR "[internal] Memory allocation error (requested %zu, replacing %zu)\n" TOY_CC_RESET, newSize, oldSize);
fprintf(stderr, TOY_CC_ERROR "[internal] Memory allocation error (requested %d, replacing %d)\n" TOY_CC_RESET, (int)newSize, (int)oldSize);
return NULL;
}
-1
View File
@@ -1 +0,0 @@
Hello, World!
-4
View File
@@ -1,4 +0,0 @@
1
8
12.5
test
-3
View File
@@ -1,3 +0,0 @@
08
12.500000
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
-164
View File
@@ -1,164 +0,0 @@
import fileio;
var PATH: string const = "scripts:/lib/file/fileio.txt";
// reset file to orginal state
fn reset() {
var writer = open(PATH, "w");
writer.write("Hello, World!\n");
writer.close();
}
// test global constants
{
assert MAX_FILENAME_SIZE > 0, "MAX_FILENAME_SIZE failed";
assert MAX_FILES_OPEN > 0, "MAX_FILES_OPEN failed";
assert END_OF_FILE == -1, "END_OF_FILE failed";
}
// test read
{
var reader = open("scripts:/lib/file/inputs.txt", "r");
assert reader.read(bool) == true, "read true bool failed";
assert reader.read(int) == 8, "read int failed";
assert reader.read(float) == 12.5, "read float failed";
assert reader.read(string) == "\ntest", "read string failed";
// invaild types
assert reader.read(type) == null, "read type failed";
assert reader.read(any) == null, "read any failed";
reader.close();
}
// test write
{
var writer = open("scripts:/lib/file/outputs.txt", "w");
assert writer.write(false) == true, "write bool failed";
assert writer.write(8) == true, "write int failed";
assert writer.write("\n") == true, "write string failed";
assert writer.write(12.5) == true, "write float failed";
assert writer.write("\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n") == true, "write long string failed";
// invaild types
assert writer.write([0, 1, 2]) == false, "write array failed";
assert writer.write(["hi": "world"]) == false, "write dict failed";
writer.close();
}
// test open and close
{
var reader = open(PATH);
assert reader != null, "open failed in reading mode";
assert reader.close() == true, "close failed";
var file = open("scripts:/doesNotExist", "r");
assert file == null, "open failed on nonexisting file";
}
// test append
{
var appender = open(PATH, "a");
assert appender != null, "open failed on appending file";
assert appender.write("appended text") == true, "append failed";
appender.close();
reset();
}
// test read extended
{
var reader = open(PATH, "r+");
assert reader != null, "open failed on read extended mode";
assert reader.write("writen text") == true, "write in read extended failed";
var result = reader.read(string);
// print result;
// assert (result == "d!\n" || result == "d!\\r\n"), "read in read extended failed";
reader.close();
reset();
}
// test write extended
{
var writer = open(PATH, "w+");
assert writer != null, "open failed on write extended mode";
assert writer.write("writen text") == true, "write in write extended failed";
writer.seek("bgn", 0);
assert writer.read(string) == "writen text", "read in write extended failed";
writer.close();
reset();
}
// test rename
{
var reader = open(PATH, "r");
assert reader.rename("scripts:/lib/file/newName.txt") == true, "rename failed";
reader.rename(PATH);
reader.close();
}
// test seek
{
var reader = open(PATH, "r");
assert reader.seek("bgn", 6) == true, "seek from bgn failed";
var contents = reader.read(string);
assert contents == " World!\n", "seek failed to move file position (1st)";
assert reader.seek("end", -2) == true, "seek from end failed";
contents = reader.read(string);
print ">>>(" + contents + ")" + string( contents.length() );
assert contents == "\n", "seek failed to move file position (2nd)";
assert reader.seek("cur", -2) == true, "seek from cur failed";
contents = reader.read(string);
assert contents == "\n", "seek failed to move file position (3rd)";
assert reader.seek("CUR", 0) == false, "seek origin failed (1st)";
assert reader.seek("End", 0) == false, "seek origin failed (2nd)";
assert reader.seek("beG", 0) == false, "seek origin failed (3rd)";
assert reader.seek("xxx", 0) == false, "seek origin failed (4th)";
reader.close();
}
// test accessors
{
var reader = open(PATH, "r");
assert reader.error() == false, "error failed";
assert reader.completed() == false, "completed failed";
assert reader.position() == 0, "position failed";
assert reader.size() == 14, "size failed";
assert reader.mode() == "r", "mode failed";
reader.read(string);
assert reader.error() == false, "error failed";
assert reader.completed() == true, "completed after read failed";
assert reader.position() == 14, "position failed";
assert reader.size() == 14, "size failed";
assert reader.mode() == "r", "mode failed";
reader.close();
}
input.close();
output.close();
print "All good";
+1 -3
View File
@@ -182,6 +182,4 @@ import math;
assert epsilionCompare(1, 1.000001) == true, "epsilionCompare(1, 1.000001) failed";
assert epsilionCompare(1, 1.001) == false, "epsilionCompare(1, 1.001) failed";
assert epsilionCompare(0, 0) == true, "epsilionCompare(0, 0) failed";
}
print "All good";
}
+1 -3
View File
@@ -18,7 +18,6 @@
#include "../repl/lib_standard.h"
#include "../repl/lib_random.h"
#include "../repl/lib_runner.h"
#include "../repl/lib_fileio.h"
#include "../repl/lib_math.h"
//supress the print output
@@ -44,7 +43,7 @@ void runBinaryWithLibrary(const unsigned char* tb, size_t size, const char* libr
Toy_initInterpreter(&interpreter);
//NOTE: supress print output for testing
// Toy_setInterpreterPrint(&interpreter, noPrintFn);
Toy_setInterpreterPrint(&interpreter, noPrintFn);
Toy_setInterpreterAssert(&interpreter, assertWrapper);
Toy_setInterpreterError(&interpreter, errorWrapper);
@@ -78,7 +77,6 @@ int main() {
{"standard.toy", "standard", Toy_hookStandard},
{"runner.toy", "runner", Toy_hookRunner},
{"random.toy", "random", Toy_hookRandom},
{"fileio.toy", "fileio", Toy_hookFileIO},
{"math.toy", "math", Toy_hookMath},
{NULL, NULL, NULL}
};
+6 -3
View File
@@ -906,7 +906,8 @@ void disassemble(const char *filename, options_t config) {
if (!strcmp(litf->fun, "MAIN")) {
printf("MAIN:\n");
printf("%s", litf->str);
printf("%s", str_replace_substr_all(litf->str, ".lit FUNCTION ", ".lit FUNCTION (code=FUN_) "));
dis_disassemble_section(&prg, prg->pc, prg->len, 0, false, config);
free(litf->fun);
free(litf->str);
@@ -915,8 +916,10 @@ void disassemble(const char *filename, options_t config) {
continue;
}
printf("FUNCTION_%s:\n", litf->fun);
printf("%s", litf->str);
printf("FUN_%s:\n", litf->fun);
char sbtr[strlen(litf->fun) + 19];
sprintf(sbtr, ".lit FUNCTION (code=FUN_%s_) ", litf->fun);
printf("%s", str_replace_substr_all(litf->str, ".lit FUNCTION ", sbtr));
queue_node_t *fqf = function_queue_front;
while (fqf != NULL) {
+32
View File
@@ -58,3 +58,35 @@ void str_append(char **str, const char *app) {
*str = realloc(*str, (strlen(*str) + strlen(app) + 1) * sizeof(char));
memcpy((*str) + strlen(*str), app, strlen(app) + 1);
}
char* str_replace_substr_all(char *mainstr, char *substr, char *newstr) {
int lenmain, lensub, i, j, lennew, startindex = -1, c;
lenmain = strlen(mainstr);
lensub = strlen(substr);
lennew = strlen(newstr);
char *result = (char*) malloc(sizeof(char) * (lenmain + 200));
for (c = 0, i = 0; i < lenmain; i++) {
if (lenmain - i >= lensub && *(mainstr + i) == *(substr)) {
startindex = i;
for (j = 1; j < lensub; j++)
if (*(mainstr + i + j) != *(substr + j)) {
startindex = -1;
break;
}
if (startindex != -1) {
for (j = 0; j < lennew; j++, c++) {
*(result + c) = *(newstr + j);
}
i = i + lensub - 1;
} else {
*(result + c) = *(mainstr + i);
c++;
}
} else {
*(result + c) = *(mainstr + i);
c++;
}
}
*(result + c) = '\0';
return result;
}
+1
View File
@@ -21,5 +21,6 @@ void dis_enqueue(void *x, queue_node_t **queue_front, queue_node_t **queue_rear,
void dis_dequeue(queue_node_t **queue_front, queue_node_t **queue_rear, uint32_t *len);
void str_append(char **str, const char *app);
char* str_replace_substr_all(char *mainstr, char *substr, char *newstr);
#endif /* UTILS_H_ */