Implemented the attribute operator, using a period

This commit is contained in:
2026-04-24 11:31:54 +10:00
parent d2ac1eeb8e
commit 9a75226491
7 changed files with 94 additions and 1 deletions
+11
View File
@@ -234,6 +234,16 @@ void Toy_private_emitAstFunctionInvokation(Toy_Bucket** bucketHandle, Toy_Ast**
(*astHandle) = tmp; (*astHandle) = tmp;
} }
void Toy_private_emitAstAttribute(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* expr) {
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast));
tmp->type = TOY_AST_ATTRIBUTE;
tmp->attribute.left = (*astHandle);
tmp->attribute.right = expr;
(*astHandle) = tmp;
}
void Toy_private_emitAstStackPop(Toy_Bucket** bucketHandle, Toy_Ast** astHandle) { void Toy_private_emitAstStackPop(Toy_Bucket** bucketHandle, Toy_Ast** astHandle) {
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast)); Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast));
@@ -294,6 +304,7 @@ const char* Toy_private_getAstTypeAsCString(Toy_AstType type) {
case TOY_AST_FN_DECLARE: return "FN_DECLARE"; case TOY_AST_FN_DECLARE: return "FN_DECLARE";
case TOY_AST_FN_INVOKE: return "FN_INVOKE"; case TOY_AST_FN_INVOKE: return "FN_INVOKE";
case TOY_AST_ATTRIBUTE: return "ATTRIBUTE";
case TOY_AST_STACK_POP: return "STACK_POP"; case TOY_AST_STACK_POP: return "STACK_POP";
+9
View File
@@ -33,6 +33,7 @@ typedef enum Toy_AstType {
TOY_AST_FN_DECLARE, TOY_AST_FN_DECLARE,
TOY_AST_FN_INVOKE, TOY_AST_FN_INVOKE,
TOY_AST_ATTRIBUTE,
TOY_AST_STACK_POP, //BUGFIX: force a single stack pop for expression statements TOY_AST_STACK_POP, //BUGFIX: force a single stack pop for expression statements
@@ -219,6 +220,12 @@ typedef struct Toy_AstFnInvoke {
Toy_Ast* args; Toy_Ast* args;
} Toy_AstFnInvoke; } Toy_AstFnInvoke;
typedef struct Toy_AstAttribute {
Toy_AstType type;
Toy_Ast* left;
Toy_Ast* right;
} Toy_AstAttribute;
typedef struct Toy_AstStackPop { typedef struct Toy_AstStackPop {
Toy_AstType type; Toy_AstType type;
Toy_Ast* child; Toy_Ast* child;
@@ -259,6 +266,7 @@ union Toy_Ast { //see 'test_ast.c' for bitness tests
Toy_AstVarAccess varAccess; Toy_AstVarAccess varAccess;
Toy_AstFnDeclare fnDeclare; Toy_AstFnDeclare fnDeclare;
Toy_AstFnInvoke fnInvoke; Toy_AstFnInvoke fnInvoke;
Toy_AstAttribute attribute;
Toy_AstStackPop stackPop; Toy_AstStackPop stackPop;
Toy_AstPass pass; Toy_AstPass pass;
Toy_AstError error; Toy_AstError error;
@@ -291,6 +299,7 @@ void Toy_private_emitAstVariableAccess(Toy_Bucket** bucketHandle, Toy_Ast** astH
void Toy_private_emitAstFunctionDeclaration(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_String* name, Toy_Ast* params, Toy_Ast* body); void Toy_private_emitAstFunctionDeclaration(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_String* name, Toy_Ast* params, Toy_Ast* body);
void Toy_private_emitAstFunctionInvokation(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* params); void Toy_private_emitAstFunctionInvokation(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* params);
void Toy_private_emitAstAttribute(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* expr);
void Toy_private_emitAstStackPop(Toy_Bucket** bucketHandle, Toy_Ast** astHandle); void Toy_private_emitAstStackPop(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);
+20
View File
@@ -1080,6 +1080,22 @@ static unsigned int writeInstructionFnInvoke(Toy_Bytecode** mb, Toy_AstFnInvoke
return 0; return 0;
} }
static unsigned int writeInstructionAttribute(Toy_Bytecode** mb, Toy_AstAttribute ast) {
//write the lhs normally
unsigned int result = writeBytecodeFromAst(mb, ast.left);
//write the attribute's identifier
result += writeBytecodeFromAst(mb, ast.right);
//exactly what this results in is type-dependant
EMIT_BYTE(mb, code,TOY_OPCODE_ATTRIBUTE);
EMIT_BYTE(mb, code, 0);
EMIT_BYTE(mb, code, 0);
EMIT_BYTE(mb, code, 0);
return 1;
}
static unsigned int writeInstructionStackPop(Toy_Bytecode** mb, Toy_AstStackPop ast) { static unsigned int writeInstructionStackPop(Toy_Bytecode** mb, Toy_AstStackPop ast) {
unsigned int result = writeBytecodeFromAst(mb, ast.child); unsigned int result = writeBytecodeFromAst(mb, ast.child);
@@ -1211,6 +1227,10 @@ static unsigned int writeBytecodeFromAst(Toy_Bytecode** mb, Toy_Ast* ast) {
result += writeInstructionFnInvoke(mb, ast->fnInvoke); result += writeInstructionFnInvoke(mb, ast->fnInvoke);
break; break;
case TOY_AST_ATTRIBUTE:
result += writeInstructionAttribute(mb, ast->attribute);
break;
case TOY_AST_STACK_POP: case TOY_AST_STACK_POP:
result += writeInstructionStackPop(mb, ast->stackPop); result += writeInstructionStackPop(mb, ast->stackPop);
break; break;
+1
View File
@@ -11,6 +11,7 @@ typedef enum Toy_OpcodeType {
TOY_OPCODE_ASSIGN_COMPOUND, //assign to a compound's internals TOY_OPCODE_ASSIGN_COMPOUND, //assign to a compound's internals
TOY_OPCODE_ACCESS, TOY_OPCODE_ACCESS,
TOY_OPCODE_INVOKE, //for calling functions TOY_OPCODE_INVOKE, //for calling functions
TOY_OPCODE_ATTRIBUTE, //for accessing parts of compounds
TOY_OPCODE_DUPLICATE, //duplicate the top of the stack TOY_OPCODE_DUPLICATE, //duplicate the top of the stack
TOY_OPCODE_ELIMINATE, //remove the top of the stack TOY_OPCODE_ELIMINATE, //remove the top of the stack
+27 -1
View File
@@ -121,6 +121,7 @@ static Toy_AstFlag compound(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_A
static Toy_AstFlag aggregate(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle); static Toy_AstFlag aggregate(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
static Toy_AstFlag unaryPostfix(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle); static Toy_AstFlag unaryPostfix(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
static Toy_AstFlag invoke(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle); static Toy_AstFlag invoke(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
static Toy_AstFlag attribute(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
//precedence definitions //precedence definitions
static ParsingTuple parsingRulesetTable[] = { static ParsingTuple parsingRulesetTable[] = {
@@ -212,7 +213,7 @@ static ParsingTuple parsingRulesetTable[] = {
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_SEMICOLON, {PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_SEMICOLON,
{PREC_GROUP,NULL,aggregate},// TOY_TOKEN_OPERATOR_COMMA, {PREC_GROUP,NULL,aggregate},// TOY_TOKEN_OPERATOR_COMMA,
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_DOT, {PREC_CALL,NULL,attribute},// TOY_TOKEN_OPERATOR_DOT,
{PREC_UNARY,NULL,binary},// TOY_TOKEN_OPERATOR_CONCAT, {PREC_UNARY,NULL,binary},// TOY_TOKEN_OPERATOR_CONCAT,
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_REST, {PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_REST,
@@ -734,6 +735,31 @@ static Toy_AstFlag invoke(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast
return TOY_AST_FLAG_INVOKATION; return TOY_AST_FLAG_INVOKATION;
} }
static Toy_AstFlag attribute(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
//infix must advance
advance(parser);
if (parser->previous.type == TOY_TOKEN_OPERATOR_DOT) {
Toy_Ast* expr = NULL;
parsePrecedence(bucketHandle, parser, &expr, PREC_PRIMARY);
//hijack access node and take the value (presumably an identifier)
if (expr->type != TOY_AST_VAR_ACCESS || expr->varAccess.child == NULL || expr->varAccess.child->type != TOY_AST_VALUE) {
printError(parser, parser->previous, "Malformed expression passed to attribute precedence rule");
Toy_private_emitAstError(bucketHandle, rootHandle);
return TOY_AST_FLAG_NONE;
}
Toy_private_emitAstAttribute(bucketHandle, rootHandle, expr->varAccess.child);
return TOY_AST_FLAG_NONE;
}
else {
printError(parser, parser->previous, "Unexpected token passed to attribute precedence rule");
Toy_private_emitAstError(bucketHandle, rootHandle);
return TOY_AST_FLAG_NONE;
}
}
//grammar rules //grammar rules
static void parsePrecedence(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle, ParsingPrecedence precRule) { static void parsePrecedence(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle, ParsingPrecedence precRule) {
//'step over' the token to parse //'step over' the token to parse
+17
View File
@@ -431,6 +431,19 @@ 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);
//URGENT: type-based attributes
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_NULL()); //tmp
//cleanup
Toy_freeValue(value);
Toy_freeValue(attribute);
}
static void processDuplicate(Toy_VM* vm) { static void processDuplicate(Toy_VM* vm) {
Toy_Value value = Toy_copyValue(&vm->memoryBucket, Toy_peekStack(&vm->stack)); Toy_Value value = Toy_copyValue(&vm->memoryBucket, Toy_peekStack(&vm->stack));
Toy_pushStack(&vm->stack, value); Toy_pushStack(&vm->stack, value);
@@ -958,6 +971,10 @@ static unsigned int process(Toy_VM* vm) {
processInvoke(vm); processInvoke(vm);
break; break;
case TOY_OPCODE_ATTRIBUTE:
processAttribute(vm);
break;
case TOY_OPCODE_DUPLICATE: case TOY_OPCODE_DUPLICATE:
processDuplicate(vm); processDuplicate(vm);
break; break;
+9
View File
@@ -0,0 +1,9 @@
#include "toy_console_colors.h"
#include <stdio.h>
#include <string.h>
int main(void) {
printf(TOY_CC_WARN "Test not yet implemented: %s\n" TOY_CC_RESET, __FILE__);
return 0;
}