mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-05-01 22:40:10 +10:00
Implemented the attribute operator, using a period
This commit is contained in:
@@ -234,6 +234,16 @@ void Toy_private_emitAstFunctionInvokation(Toy_Bucket** bucketHandle, Toy_Ast**
|
||||
(*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) {
|
||||
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_INVOKE: return "FN_INVOKE";
|
||||
case TOY_AST_ATTRIBUTE: return "ATTRIBUTE";
|
||||
|
||||
case TOY_AST_STACK_POP: return "STACK_POP";
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ typedef enum Toy_AstType {
|
||||
|
||||
TOY_AST_FN_DECLARE,
|
||||
TOY_AST_FN_INVOKE,
|
||||
TOY_AST_ATTRIBUTE,
|
||||
|
||||
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_AstFnInvoke;
|
||||
|
||||
typedef struct Toy_AstAttribute {
|
||||
Toy_AstType type;
|
||||
Toy_Ast* left;
|
||||
Toy_Ast* right;
|
||||
} Toy_AstAttribute;
|
||||
|
||||
typedef struct Toy_AstStackPop {
|
||||
Toy_AstType type;
|
||||
Toy_Ast* child;
|
||||
@@ -259,6 +266,7 @@ union Toy_Ast { //see 'test_ast.c' for bitness tests
|
||||
Toy_AstVarAccess varAccess;
|
||||
Toy_AstFnDeclare fnDeclare;
|
||||
Toy_AstFnInvoke fnInvoke;
|
||||
Toy_AstAttribute attribute;
|
||||
Toy_AstStackPop stackPop;
|
||||
Toy_AstPass pass;
|
||||
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_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);
|
||||
|
||||
|
||||
@@ -1080,6 +1080,22 @@ static unsigned int writeInstructionFnInvoke(Toy_Bytecode** mb, Toy_AstFnInvoke
|
||||
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) {
|
||||
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);
|
||||
break;
|
||||
|
||||
case TOY_AST_ATTRIBUTE:
|
||||
result += writeInstructionAttribute(mb, ast->attribute);
|
||||
break;
|
||||
|
||||
case TOY_AST_STACK_POP:
|
||||
result += writeInstructionStackPop(mb, ast->stackPop);
|
||||
break;
|
||||
|
||||
@@ -11,6 +11,7 @@ typedef enum Toy_OpcodeType {
|
||||
TOY_OPCODE_ASSIGN_COMPOUND, //assign to a compound's internals
|
||||
TOY_OPCODE_ACCESS,
|
||||
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_ELIMINATE, //remove the top of the stack
|
||||
|
||||
|
||||
+27
-1
@@ -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 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 attribute(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
||||
|
||||
//precedence definitions
|
||||
static ParsingTuple parsingRulesetTable[] = {
|
||||
@@ -212,7 +213,7 @@ static ParsingTuple parsingRulesetTable[] = {
|
||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_SEMICOLON,
|
||||
{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_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;
|
||||
}
|
||||
|
||||
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
|
||||
static void parsePrecedence(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle, ParsingPrecedence precRule) {
|
||||
//'step over' the token to parse
|
||||
|
||||
@@ -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) {
|
||||
Toy_Value value = Toy_copyValue(&vm->memoryBucket, Toy_peekStack(&vm->stack));
|
||||
Toy_pushStack(&vm->stack, value);
|
||||
@@ -958,6 +971,10 @@ static unsigned int process(Toy_VM* vm) {
|
||||
processInvoke(vm);
|
||||
break;
|
||||
|
||||
case TOY_OPCODE_ATTRIBUTE:
|
||||
processAttribute(vm);
|
||||
break;
|
||||
|
||||
case TOY_OPCODE_DUPLICATE:
|
||||
processDuplicate(vm);
|
||||
break;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user