mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-05-06 08:50:10 +10:00
Implemented the following attributes:
* String.length * String.asUpper * String.asLower * array.length * array.pushBack(x) * array.popBack() The remaining attributes are listed in 'toy_attributes.h'
This commit is contained in:
@@ -85,6 +85,7 @@ typedef enum Toy_AstFlag {
|
||||
TOY_AST_FLAG_POSTFIX_DECREMENT = 44,
|
||||
|
||||
TOY_AST_FLAG_INVOKATION = 45,
|
||||
TOY_AST_FLAG_ATTRIBUTE = 46,
|
||||
|
||||
// TOY_AST_FLAG_TERNARY,
|
||||
} Toy_AstFlag;
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
#include "toy_attributes.h"
|
||||
#include "toy_console_colors.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
Toy_Value handleStringAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute) {
|
||||
if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "length", 6) == 0) {
|
||||
return TOY_VALUE_FROM_INTEGER(TOY_VALUE_AS_STRING(compound)->info.length);
|
||||
}
|
||||
else if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "asUpper", 7) == 0) {
|
||||
char* buffer = Toy_getStringRaw(TOY_VALUE_AS_STRING(compound));
|
||||
for (int i = 0; buffer[i] != '\0'; i++) {
|
||||
buffer[i] = toupper(buffer[i]);
|
||||
}
|
||||
Toy_String* str = Toy_createStringLength(&vm->memoryBucket, buffer, strlen(buffer));
|
||||
free(buffer);
|
||||
return TOY_VALUE_FROM_STRING(str);
|
||||
}
|
||||
else if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "asLower", 7) == 0) {
|
||||
char* buffer = Toy_getStringRaw(TOY_VALUE_AS_STRING(compound));
|
||||
for (int i = 0; buffer[i] != '\0'; i++) {
|
||||
buffer[i] = tolower(buffer[i]);
|
||||
}
|
||||
Toy_String* str = Toy_createStringLength(&vm->memoryBucket, buffer, strlen(buffer));
|
||||
free(buffer);
|
||||
return TOY_VALUE_FROM_STRING(str);
|
||||
}
|
||||
else {
|
||||
char buffer[256];
|
||||
snprintf(buffer, 256, "Unknown attribute '%s' of type '%s'", TOY_VALUE_AS_STRING(attribute)->leaf.data, Toy_private_getValueTypeAsCString(compound.type));
|
||||
Toy_error(buffer);
|
||||
return TOY_VALUE_FROM_NULL();
|
||||
}
|
||||
}
|
||||
|
||||
static void attr_arrayPushBack(Toy_VM* vm) {
|
||||
Toy_Value compound = Toy_popStack(&vm->stack);
|
||||
Toy_Value element = Toy_popStack(&vm->stack);
|
||||
|
||||
Toy_Array* array = TOY_VALUE_AS_ARRAY(compound);
|
||||
|
||||
//check the capacity limit
|
||||
if (array->count == array->capacity) {
|
||||
//correct the source value's pointer
|
||||
array = Toy_resizeArray(array, array->capacity * TOY_ARRAY_EXPANSION_RATE);
|
||||
if (TOY_VALUE_IS_REFERENCE(compound) && compound.as.reference->type == TOY_VALUE_ARRAY) {
|
||||
compound.as.reference->as.array = array;
|
||||
}
|
||||
else {
|
||||
char buffer[256];
|
||||
snprintf(buffer, 256, "Unknown error at %s %d", __FILE__, __LINE__);
|
||||
Toy_error(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
array->data[array->count] = element;
|
||||
array->count++;
|
||||
}
|
||||
|
||||
static void attr_arrayPopBack(Toy_VM* vm) {
|
||||
Toy_Value compound = Toy_popStack(&vm->stack);
|
||||
|
||||
Toy_Array* array = TOY_VALUE_AS_ARRAY(compound);
|
||||
|
||||
//empty returns nothing
|
||||
if (array->count == 0) {
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_NULL());
|
||||
return;
|
||||
}
|
||||
|
||||
Toy_Value element = array->data[array->count-1];
|
||||
array->count--;
|
||||
|
||||
Toy_pushStack(&vm->stack, element);
|
||||
}
|
||||
|
||||
static void attr_arrayForEach(Toy_VM* vm) {
|
||||
(void)vm;
|
||||
//URGENT: attr_arrayForEach
|
||||
}
|
||||
|
||||
static void attr_arraySort(Toy_VM* vm) {
|
||||
(void)vm;
|
||||
//URGENT: attr_arraySort
|
||||
}
|
||||
|
||||
Toy_Value handleArrayAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute) {
|
||||
if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "length", 6) == 0) {
|
||||
return TOY_VALUE_FROM_INTEGER(TOY_VALUE_AS_ARRAY(compound)->count);
|
||||
}
|
||||
else if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "pushBack", 8) == 0) {
|
||||
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_arrayPushBack);
|
||||
return TOY_VALUE_FROM_FUNCTION(fn);
|
||||
}
|
||||
else if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "popBack", 7) == 0) {
|
||||
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_arrayPopBack);
|
||||
return TOY_VALUE_FROM_FUNCTION(fn);
|
||||
}
|
||||
else if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "forEach", 7) == 0) {
|
||||
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_arrayForEach);
|
||||
return TOY_VALUE_FROM_FUNCTION(fn);
|
||||
}
|
||||
else if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "sort", 4) == 0) {
|
||||
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_arraySort);
|
||||
return TOY_VALUE_FROM_FUNCTION(fn);
|
||||
}
|
||||
else {
|
||||
char buffer[256];
|
||||
snprintf(buffer, 256, "Unknown attribute '%s' of type '%s'", TOY_VALUE_AS_STRING(attribute)->leaf.data, Toy_private_getValueTypeAsCString(compound.type));
|
||||
Toy_error(buffer);
|
||||
return TOY_VALUE_FROM_NULL();
|
||||
}
|
||||
|
||||
return TOY_VALUE_FROM_NULL();
|
||||
}
|
||||
|
||||
Toy_Value handleTableAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute) {
|
||||
//URGENT: handleTableAttributes
|
||||
(void)vm;
|
||||
(void)compound;
|
||||
(void)attribute;
|
||||
return TOY_VALUE_FROM_NULL();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "toy_value.h"
|
||||
#include "toy_vm.h"
|
||||
|
||||
Toy_Value handleStringAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute);
|
||||
Toy_Value handleArrayAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute);
|
||||
Toy_Value handleTableAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute);
|
||||
|
||||
// string.length
|
||||
// string.asUpper
|
||||
// string.asLower
|
||||
// array.length
|
||||
// array.pushBack(x)
|
||||
// array.popBack()
|
||||
// array.forEach(fn) // fn(x) -> void
|
||||
// array.sort(fn) // fn(a,b) -> int
|
||||
// table.length
|
||||
// table.insert(x)
|
||||
// table.hasKey(x)
|
||||
// table.remove(x)
|
||||
// table.forEach(fn) // fn(x) -> void
|
||||
@@ -800,7 +800,7 @@ static unsigned int writeInstructionVarDeclare(Toy_Bytecode** mb, Toy_AstVarDecl
|
||||
static unsigned int writeInstructionAssign(Toy_Bytecode** mb, Toy_AstVarAssign ast, bool chainedAssignment) {
|
||||
unsigned int result = 0;
|
||||
|
||||
//URGENT: flip the order of target & value, to allow chained assignment AND multiple return values
|
||||
//BUG: flip the order of target & value, to allow chained assignment AND multiple return values
|
||||
|
||||
//target is a variable name
|
||||
if (ast.target->type == TOY_AST_VALUE && TOY_VALUE_IS_STRING(ast.target->value.value)) {
|
||||
|
||||
+1
-1
@@ -751,7 +751,7 @@ static Toy_AstFlag attribute(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_
|
||||
}
|
||||
|
||||
Toy_private_emitAstAttribute(bucketHandle, rootHandle, expr->varAccess.child);
|
||||
return TOY_AST_FLAG_NONE;
|
||||
return TOY_AST_FLAG_ATTRIBUTE;
|
||||
}
|
||||
else {
|
||||
printError(parser, parser->previous, "Unexpected token passed to attribute precedence rule");
|
||||
|
||||
+29
-12
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "toy_print.h"
|
||||
#include "toy_opcodes.h"
|
||||
#include "toy_attributes.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -434,22 +435,38 @@ static void processInvoke(Toy_VM* vm) {
|
||||
static void processAttribute(Toy_VM* vm) {
|
||||
//get the compound & attribute
|
||||
Toy_Value attribute = Toy_popStack(&vm->stack);
|
||||
Toy_Value value = Toy_popStack(&vm->stack);
|
||||
Toy_Value compound = Toy_popStack(&vm->stack);
|
||||
|
||||
//URGENT: type-based attributes
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_NULL()); //tmp
|
||||
Toy_Value result = TOY_VALUE_FROM_NULL();
|
||||
|
||||
//string.length
|
||||
//array.length
|
||||
//array.pushFront(x)
|
||||
//array.pushBack(x)
|
||||
//array.popFront()
|
||||
//array.popBack()
|
||||
//array.toString()
|
||||
//table etc.
|
||||
//type-based attributes
|
||||
if (TOY_VALUE_IS_STRING(compound)) {
|
||||
result = handleStringAttributes(vm, compound, attribute);
|
||||
}
|
||||
else if (TOY_VALUE_IS_ARRAY(compound)) {
|
||||
result = handleArrayAttributes(vm, compound, attribute);
|
||||
}
|
||||
else if (TOY_VALUE_IS_TABLE(compound)) {
|
||||
result = handleTableAttributes(vm, compound, attribute);
|
||||
}
|
||||
else {
|
||||
char buffer[256];
|
||||
snprintf(buffer, 256, "Can't access an attribute of type '%s'", Toy_private_getValueTypeAsCString(compound.type));
|
||||
Toy_error(buffer);
|
||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_NULL());
|
||||
return;
|
||||
}
|
||||
|
||||
//BUGFIX: check for callable native functions, so they can access the compound too
|
||||
if (TOY_VALUE_IS_FUNCTION(result) && TOY_VALUE_AS_FUNCTION(result)->type == TOY_FUNCTION_NATIVE) {
|
||||
//WONTFIX: `print array.pushBack;' will leave the compound's reference on the stack
|
||||
Toy_pushStack(&vm->stack, compound);
|
||||
}
|
||||
|
||||
//leave the result on the stack
|
||||
Toy_pushStack(&vm->stack, result);
|
||||
|
||||
//cleanup
|
||||
Toy_freeValue(value);
|
||||
Toy_freeValue(attribute);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user