mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Added indexing to strings, tests still needed
This commit is contained in:
@@ -84,6 +84,17 @@ void Toy_private_emitAstGroup(Toy_Bucket** bucketHandle, Toy_Ast** astHandle) {
|
|||||||
(*astHandle) = tmp;
|
(*astHandle) = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Toy_private_emitAstCompound(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_AstFlag flag, Toy_Ast* right) {
|
||||||
|
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast));
|
||||||
|
|
||||||
|
tmp->type = TOY_AST_COMPOUND;
|
||||||
|
tmp->compound.flag = flag;
|
||||||
|
tmp->compound.left = *astHandle; //left-recursive
|
||||||
|
tmp->compound.right = right;
|
||||||
|
|
||||||
|
(*astHandle) = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
void Toy_private_emitAstPrint(Toy_Bucket** bucketHandle, Toy_Ast** astHandle) {
|
void Toy_private_emitAstPrint(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));
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ typedef enum Toy_AstType {
|
|||||||
TOY_AST_BINARY,
|
TOY_AST_BINARY,
|
||||||
TOY_AST_COMPARE,
|
TOY_AST_COMPARE,
|
||||||
TOY_AST_GROUP,
|
TOY_AST_GROUP,
|
||||||
|
TOY_AST_COMPOUND,
|
||||||
|
|
||||||
TOY_AST_PRINT,
|
TOY_AST_PRINT,
|
||||||
|
|
||||||
@@ -52,14 +53,17 @@ typedef enum Toy_AstFlag {
|
|||||||
TOY_AST_FLAG_COMPARE_GREATER = 24,
|
TOY_AST_FLAG_COMPARE_GREATER = 24,
|
||||||
TOY_AST_FLAG_COMPARE_GREATER_EQUAL = 25,
|
TOY_AST_FLAG_COMPARE_GREATER_EQUAL = 25,
|
||||||
|
|
||||||
TOY_AST_FLAG_AND = 30,
|
TOY_AST_FLAG_COMPOUND_COLLECTION = 30,
|
||||||
TOY_AST_FLAG_OR = 31,
|
TOY_AST_FLAG_COMPOUND_INDEX = 31,
|
||||||
TOY_AST_FLAG_CONCAT = 32,
|
|
||||||
|
TOY_AST_FLAG_AND = 40,
|
||||||
|
TOY_AST_FLAG_OR = 41,
|
||||||
|
TOY_AST_FLAG_CONCAT = 42,
|
||||||
|
|
||||||
//unary flags
|
//unary flags
|
||||||
TOY_AST_FLAG_NEGATE = 33,
|
TOY_AST_FLAG_NEGATE = 43,
|
||||||
TOY_AST_FLAG_INCREMENT = 34,
|
TOY_AST_FLAG_INCREMENT = 44,
|
||||||
TOY_AST_FLAG_DECREMENT = 35,
|
TOY_AST_FLAG_DECREMENT = 45,
|
||||||
|
|
||||||
// TOY_AST_FLAG_TERNARY,
|
// TOY_AST_FLAG_TERNARY,
|
||||||
} Toy_AstFlag;
|
} Toy_AstFlag;
|
||||||
@@ -105,6 +109,13 @@ typedef struct Toy_AstGroup {
|
|||||||
Toy_Ast* child;
|
Toy_Ast* child;
|
||||||
} Toy_AstGroup;
|
} Toy_AstGroup;
|
||||||
|
|
||||||
|
typedef struct Toy_AstCompound {
|
||||||
|
Toy_AstType type;
|
||||||
|
Toy_AstFlag flag;
|
||||||
|
Toy_Ast* left;
|
||||||
|
Toy_Ast* right;
|
||||||
|
} Toy_AstCompound;
|
||||||
|
|
||||||
typedef struct Toy_AstPrint {
|
typedef struct Toy_AstPrint {
|
||||||
Toy_AstType type;
|
Toy_AstType type;
|
||||||
Toy_Ast* child;
|
Toy_Ast* child;
|
||||||
@@ -148,6 +159,7 @@ union Toy_Ast { //32 | 64 BITNESS
|
|||||||
Toy_AstBinary binary; //16 | 24
|
Toy_AstBinary binary; //16 | 24
|
||||||
Toy_AstCompare compare; //16 | 24
|
Toy_AstCompare compare; //16 | 24
|
||||||
Toy_AstGroup group; //8 | 16
|
Toy_AstGroup group; //8 | 16
|
||||||
|
Toy_AstCompound compound; //16 | 24
|
||||||
Toy_AstPrint print; //8 | 16
|
Toy_AstPrint print; //8 | 16
|
||||||
Toy_AstVarDeclare varDeclare; //16 | 24
|
Toy_AstVarDeclare varDeclare; //16 | 24
|
||||||
Toy_AstVarAssign varAssign; //16 | 24
|
Toy_AstVarAssign varAssign; //16 | 24
|
||||||
@@ -165,6 +177,7 @@ void Toy_private_emitAstUnary(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, To
|
|||||||
void Toy_private_emitAstBinary(Toy_Bucket** bucketHandle, Toy_Ast** astHandle,Toy_AstFlag flag, Toy_Ast* right);
|
void Toy_private_emitAstBinary(Toy_Bucket** bucketHandle, Toy_Ast** astHandle,Toy_AstFlag flag, Toy_Ast* right);
|
||||||
void Toy_private_emitAstCompare(Toy_Bucket** bucketHandle, Toy_Ast** astHandle,Toy_AstFlag flag, Toy_Ast* right);
|
void Toy_private_emitAstCompare(Toy_Bucket** bucketHandle, Toy_Ast** astHandle,Toy_AstFlag flag, Toy_Ast* right);
|
||||||
void Toy_private_emitAstGroup(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);
|
void Toy_private_emitAstGroup(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);
|
||||||
|
void Toy_private_emitAstCompound(Toy_Bucket** bucketHandle, Toy_Ast** astHandle,Toy_AstFlag flag, Toy_Ast* right);
|
||||||
|
|
||||||
void Toy_private_emitAstPrint(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);
|
void Toy_private_emitAstPrint(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ typedef enum Toy_OpcodeType {
|
|||||||
//various action instructions
|
//various action instructions
|
||||||
TOY_OPCODE_PRINT,
|
TOY_OPCODE_PRINT,
|
||||||
TOY_OPCODE_CONCAT,
|
TOY_OPCODE_CONCAT,
|
||||||
|
TOY_OPCODE_INDEX,
|
||||||
//TODO: clear the program stack?
|
//TODO: clear the program stack?
|
||||||
|
|
||||||
//meta instructions
|
//meta instructions
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ static Toy_AstFlag literal(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_As
|
|||||||
static Toy_AstFlag unary(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
static Toy_AstFlag unary(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
||||||
static Toy_AstFlag binary(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
static Toy_AstFlag binary(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
||||||
static Toy_AstFlag group(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
static Toy_AstFlag group(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
||||||
|
static Toy_AstFlag compound(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
||||||
|
|
||||||
//precedence definitions
|
//precedence definitions
|
||||||
static ParsingTuple parsingRulesetTable[] = {
|
static ParsingTuple parsingRulesetTable[] = {
|
||||||
@@ -194,7 +195,7 @@ static ParsingTuple parsingRulesetTable[] = {
|
|||||||
//structural operators
|
//structural operators
|
||||||
{PREC_NONE,group,NULL},// TOY_TOKEN_OPERATOR_PAREN_LEFT,
|
{PREC_NONE,group,NULL},// TOY_TOKEN_OPERATOR_PAREN_LEFT,
|
||||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_PAREN_RIGHT,
|
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_PAREN_RIGHT,
|
||||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_BRACKET_LEFT,
|
{PREC_CALL,NULL,compound},// TOY_TOKEN_OPERATOR_BRACKET_LEFT,
|
||||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_BRACKET_RIGHT,
|
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_BRACKET_RIGHT,
|
||||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_BRACE_LEFT,
|
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_BRACE_LEFT,
|
||||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_BRACE_RIGHT,
|
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_BRACE_RIGHT,
|
||||||
@@ -207,7 +208,7 @@ static ParsingTuple parsingRulesetTable[] = {
|
|||||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_COLON,
|
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_COLON,
|
||||||
|
|
||||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_SEMICOLON, // ;
|
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_SEMICOLON, // ;
|
||||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_COMMA, // ,
|
{PREC_CALL,NULL,compound},// TOY_TOKEN_OPERATOR_COMMA, // ,
|
||||||
|
|
||||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_DOT, // .
|
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_DOT, // .
|
||||||
{PREC_CALL,NULL,binary},// TOY_TOKEN_OPERATOR_CONCAT, // ..
|
{PREC_CALL,NULL,binary},// TOY_TOKEN_OPERATOR_CONCAT, // ..
|
||||||
@@ -557,6 +558,26 @@ static Toy_AstFlag group(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast*
|
|||||||
return TOY_AST_FLAG_NONE;
|
return TOY_AST_FLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Toy_AstFlag compound(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
|
||||||
|
//infix must advance
|
||||||
|
advance(parser);
|
||||||
|
|
||||||
|
if (parser->previous.type == TOY_TOKEN_OPERATOR_COMMA) {
|
||||||
|
parsePrecedence(bucketHandle, parser, rootHandle, PREC_ASSIGNMENT + 1);
|
||||||
|
return TOY_AST_FLAG_COMPOUND_COLLECTION;
|
||||||
|
}
|
||||||
|
else if (parser->previous.type == TOY_TOKEN_OPERATOR_BRACKET_LEFT) {
|
||||||
|
parsePrecedence(bucketHandle, parser, rootHandle, PREC_ASSIGNMENT + 1);
|
||||||
|
consume(parser, TOY_TOKEN_OPERATOR_BRACKET_RIGHT, "Expected ']' at the end of index expression");
|
||||||
|
return TOY_AST_FLAG_COMPOUND_INDEX;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printError(parser, parser->previous, "Unexpected token passed to compound precedence rule");
|
||||||
|
Toy_private_emitAstError(bucketHandle, rootHandle);
|
||||||
|
return TOY_AST_FLAG_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static ParsingTuple* getParsingRule(Toy_TokenType type) {
|
static ParsingTuple* getParsingRule(Toy_TokenType type) {
|
||||||
return &parsingRulesetTable[type];
|
return &parsingRulesetTable[type];
|
||||||
}
|
}
|
||||||
@@ -605,6 +626,7 @@ static void parsePrecedence(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_A
|
|||||||
(*rootHandle) = ptr;
|
(*rootHandle) = ptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
//eww, gross
|
||||||
else if (flag >= 10 && flag <= 19) {
|
else if (flag >= 10 && flag <= 19) {
|
||||||
Toy_String* name = Toy_createNameStringLength(bucketHandle, prevToken.lexeme, prevToken.length, TOY_VALUE_UNKNOWN, false);
|
Toy_String* name = Toy_createNameStringLength(bucketHandle, prevToken.lexeme, prevToken.length, TOY_VALUE_UNKNOWN, false);
|
||||||
Toy_private_emitAstVariableAssignment(bucketHandle, rootHandle, name, flag, ptr);
|
Toy_private_emitAstVariableAssignment(bucketHandle, rootHandle, name, flag, ptr);
|
||||||
@@ -612,6 +634,9 @@ static void parsePrecedence(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_A
|
|||||||
else if (flag >= 20 && flag <= 29) {
|
else if (flag >= 20 && flag <= 29) {
|
||||||
Toy_private_emitAstCompare(bucketHandle, rootHandle, flag, ptr);
|
Toy_private_emitAstCompare(bucketHandle, rootHandle, flag, ptr);
|
||||||
}
|
}
|
||||||
|
else if (flag >= 30 && flag <= 39) {
|
||||||
|
Toy_private_emitAstCompound(bucketHandle, rootHandle, flag, ptr);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
Toy_private_emitAstBinary(bucketHandle, rootHandle, flag, ptr);
|
Toy_private_emitAstBinary(bucketHandle, rootHandle, flag, ptr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ static void emitToJumpTable(Toy_Routine** rt, unsigned int startAddr) {
|
|||||||
EMIT_INT(rt, jumps, startAddr); //save address at the jump index
|
EMIT_INT(rt, jumps, startAddr); //save address at the jump index
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emitString(Toy_Routine** rt, Toy_String* str) {
|
static unsigned int emitString(Toy_Routine** rt, Toy_String* str) {
|
||||||
//4-byte alignment
|
//4-byte alignment
|
||||||
unsigned int length = str->length + 1;
|
unsigned int length = str->length + 1;
|
||||||
if (length % 4 != 0) {
|
if (length % 4 != 0) {
|
||||||
@@ -87,11 +87,13 @@ static void emitString(Toy_Routine** rt, Toy_String* str) {
|
|||||||
|
|
||||||
//mark the jump position
|
//mark the jump position
|
||||||
emitToJumpTable(rt, startAddr);
|
emitToJumpTable(rt, startAddr);
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeRoutineCode(Toy_Routine** rt, Toy_Ast* ast); //forward declare for recursion
|
static unsigned int writeRoutineCode(Toy_Routine** rt, Toy_Ast* ast); //forward declare for recursion
|
||||||
|
|
||||||
static void writeInstructionValue(Toy_Routine** rt, Toy_AstValue ast) {
|
static unsigned int writeInstructionValue(Toy_Routine** rt, Toy_AstValue ast) {
|
||||||
EMIT_BYTE(rt, code, TOY_OPCODE_READ);
|
EMIT_BYTE(rt, code, TOY_OPCODE_READ);
|
||||||
EMIT_BYTE(rt, code, ast.value.type);
|
EMIT_BYTE(rt, code, ast.value.type);
|
||||||
|
|
||||||
@@ -128,17 +130,19 @@ static void writeInstructionValue(Toy_Routine** rt, Toy_AstValue ast) {
|
|||||||
EMIT_BYTE(rt, code, TOY_STRING_LEAF); //normal string
|
EMIT_BYTE(rt, code, TOY_STRING_LEAF); //normal string
|
||||||
EMIT_BYTE(rt, code, 0); //can't store the length
|
EMIT_BYTE(rt, code, 0); //can't store the length
|
||||||
|
|
||||||
emitString(rt, TOY_VALUE_AS_STRING(ast.value));
|
return emitString(rt, TOY_VALUE_AS_STRING(ast.value));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid AST type found: Unknown value type\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid AST type found: Unknown value type\n" TOY_CC_RESET);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeInstructionUnary(Toy_Routine** rt, Toy_AstUnary ast) {
|
static unsigned int writeInstructionUnary(Toy_Routine** rt, Toy_AstUnary ast) {
|
||||||
//working with a stack means the child gets placed first
|
//working with a stack means the child gets placed first
|
||||||
writeRoutineCode(rt, ast.child);
|
unsigned int result = writeRoutineCode(rt, ast.child);
|
||||||
|
|
||||||
if (ast.flag == TOY_AST_FLAG_NEGATE) {
|
if (ast.flag == TOY_AST_FLAG_NEGATE) {
|
||||||
EMIT_BYTE(rt, code, TOY_OPCODE_NEGATE);
|
EMIT_BYTE(rt, code, TOY_OPCODE_NEGATE);
|
||||||
@@ -152,9 +156,11 @@ static void writeInstructionUnary(Toy_Routine** rt, Toy_AstUnary ast) {
|
|||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid AST unary flag found\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid AST unary flag found\n" TOY_CC_RESET);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeInstructionBinary(Toy_Routine** rt, Toy_AstBinary ast) {
|
static unsigned int writeInstructionBinary(Toy_Routine** rt, Toy_AstBinary ast) {
|
||||||
//left, then right, then the binary's operation
|
//left, then right, then the binary's operation
|
||||||
writeRoutineCode(rt, ast.left);
|
writeRoutineCode(rt, ast.left);
|
||||||
writeRoutineCode(rt, ast.right);
|
writeRoutineCode(rt, ast.right);
|
||||||
@@ -194,9 +200,11 @@ static void writeInstructionBinary(Toy_Routine** rt, Toy_AstBinary ast) {
|
|||||||
EMIT_BYTE(rt, code,TOY_OPCODE_PASS); //checked in compound assignments
|
EMIT_BYTE(rt, code,TOY_OPCODE_PASS); //checked in compound assignments
|
||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
|
|
||||||
|
return 1; //leaves only 1 value on the stack
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeInstructionCompare(Toy_Routine** rt, Toy_AstCompare ast) {
|
static unsigned int writeInstructionCompare(Toy_Routine** rt, Toy_AstCompare ast) {
|
||||||
//left, then right, then the compare's operation
|
//left, then right, then the compare's operation
|
||||||
writeRoutineCode(rt, ast.left);
|
writeRoutineCode(rt, ast.left);
|
||||||
writeRoutineCode(rt, ast.right);
|
writeRoutineCode(rt, ast.right);
|
||||||
@@ -210,7 +218,7 @@ static void writeInstructionCompare(Toy_Routine** rt, Toy_AstCompare ast) {
|
|||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
|
|
||||||
return;
|
return 1;
|
||||||
}
|
}
|
||||||
else if (ast.flag == TOY_AST_FLAG_COMPARE_LESS) {
|
else if (ast.flag == TOY_AST_FLAG_COMPARE_LESS) {
|
||||||
EMIT_BYTE(rt, code,TOY_OPCODE_COMPARE_LESS);
|
EMIT_BYTE(rt, code,TOY_OPCODE_COMPARE_LESS);
|
||||||
@@ -234,13 +242,45 @@ static void writeInstructionCompare(Toy_Routine** rt, Toy_AstCompare ast) {
|
|||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
|
|
||||||
|
return 1; //leaves only 1 value on the stack
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeInstructionGroup(Toy_Routine** rt, Toy_AstGroup ast) {
|
static unsigned int writeInstructionGroup(Toy_Routine** rt, Toy_AstGroup ast) {
|
||||||
writeRoutineCode(rt, ast.child);
|
//not certain what this leaves
|
||||||
|
return writeRoutineCode(rt, ast.child);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeInstructionPrint(Toy_Routine** rt, Toy_AstPrint ast) {
|
static unsigned int writeInstructionCompound(Toy_Routine** rt, Toy_AstCompound ast) {
|
||||||
|
unsigned int result = 0;
|
||||||
|
|
||||||
|
//left, then right
|
||||||
|
result += writeRoutineCode(rt, ast.left);
|
||||||
|
result += writeRoutineCode(rt, ast.right);
|
||||||
|
|
||||||
|
if (ast.flag == TOY_AST_FLAG_COMPOUND_COLLECTION) {
|
||||||
|
//collections are handled above
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if (ast.flag == TOY_AST_FLAG_COMPOUND_INDEX) {
|
||||||
|
//value[index, length]
|
||||||
|
EMIT_BYTE(rt, code, TOY_OPCODE_INDEX);
|
||||||
|
EMIT_BYTE(rt, code, result);
|
||||||
|
|
||||||
|
//4-byte alignment
|
||||||
|
EMIT_BYTE(rt, code,0);
|
||||||
|
EMIT_BYTE(rt, code,0);
|
||||||
|
|
||||||
|
return 1; //leaves only 1 value on the stack
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid AST compound flag found\n" TOY_CC_RESET);
|
||||||
|
exit(-1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int writeInstructionPrint(Toy_Routine** rt, Toy_AstPrint ast) {
|
||||||
//the thing to print
|
//the thing to print
|
||||||
writeRoutineCode(rt, ast.child);
|
writeRoutineCode(rt, ast.child);
|
||||||
|
|
||||||
@@ -251,9 +291,11 @@ static void writeInstructionPrint(Toy_Routine** rt, Toy_AstPrint ast) {
|
|||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeInstructionVarDeclare(Toy_Routine** rt, Toy_AstVarDeclare ast) {
|
static unsigned int writeInstructionVarDeclare(Toy_Routine** rt, Toy_AstVarDeclare ast) {
|
||||||
//initial value
|
//initial value
|
||||||
writeRoutineCode(rt, ast.expr);
|
writeRoutineCode(rt, ast.expr);
|
||||||
|
|
||||||
@@ -264,9 +306,13 @@ static void writeInstructionVarDeclare(Toy_Routine** rt, Toy_AstVarDeclare ast)
|
|||||||
EMIT_BYTE(rt, code, Toy_getNameStringConstant(ast.name) ? 1 : 0); //check for constness
|
EMIT_BYTE(rt, code, Toy_getNameStringConstant(ast.name) ? 1 : 0); //check for constness
|
||||||
|
|
||||||
emitString(rt, ast.name);
|
emitString(rt, ast.name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeInstructionAssign(Toy_Routine** rt, Toy_AstVarAssign ast) {
|
static unsigned int writeInstructionAssign(Toy_Routine** rt, Toy_AstVarAssign ast) {
|
||||||
|
unsigned int result = 0;
|
||||||
|
|
||||||
//name, duplicate, right, opcode
|
//name, duplicate, right, opcode
|
||||||
if (ast.flag == TOY_AST_FLAG_ASSIGN) {
|
if (ast.flag == TOY_AST_FLAG_ASSIGN) {
|
||||||
EMIT_BYTE(rt, code, TOY_OPCODE_READ);
|
EMIT_BYTE(rt, code, TOY_OPCODE_READ);
|
||||||
@@ -275,7 +321,7 @@ static void writeInstructionAssign(Toy_Routine** rt, Toy_AstVarAssign ast) {
|
|||||||
EMIT_BYTE(rt, code, ast.name->length); //store the length (max 255)
|
EMIT_BYTE(rt, code, ast.name->length); //store the length (max 255)
|
||||||
|
|
||||||
emitString(rt, ast.name);
|
emitString(rt, ast.name);
|
||||||
writeRoutineCode(rt, ast.expr);
|
result += writeRoutineCode(rt, ast.expr);
|
||||||
|
|
||||||
EMIT_BYTE(rt, code, TOY_OPCODE_ASSIGN);
|
EMIT_BYTE(rt, code, TOY_OPCODE_ASSIGN);
|
||||||
EMIT_BYTE(rt, code, 0);
|
EMIT_BYTE(rt, code, 0);
|
||||||
@@ -293,7 +339,7 @@ static void writeInstructionAssign(Toy_Routine** rt, Toy_AstVarAssign ast) {
|
|||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
|
|
||||||
writeRoutineCode(rt, ast.expr);
|
result += writeRoutineCode(rt, ast.expr);
|
||||||
|
|
||||||
EMIT_BYTE(rt, code,TOY_OPCODE_ADD);
|
EMIT_BYTE(rt, code,TOY_OPCODE_ADD);
|
||||||
EMIT_BYTE(rt, code,TOY_OPCODE_ASSIGN); //squeezed
|
EMIT_BYTE(rt, code,TOY_OPCODE_ASSIGN); //squeezed
|
||||||
@@ -311,7 +357,7 @@ static void writeInstructionAssign(Toy_Routine** rt, Toy_AstVarAssign ast) {
|
|||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
|
|
||||||
writeRoutineCode(rt, ast.expr);
|
result += writeRoutineCode(rt, ast.expr);
|
||||||
|
|
||||||
EMIT_BYTE(rt, code,TOY_OPCODE_SUBTRACT);
|
EMIT_BYTE(rt, code,TOY_OPCODE_SUBTRACT);
|
||||||
EMIT_BYTE(rt, code,TOY_OPCODE_ASSIGN); //squeezed
|
EMIT_BYTE(rt, code,TOY_OPCODE_ASSIGN); //squeezed
|
||||||
@@ -329,7 +375,7 @@ static void writeInstructionAssign(Toy_Routine** rt, Toy_AstVarAssign ast) {
|
|||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
|
|
||||||
writeRoutineCode(rt, ast.expr);
|
result += writeRoutineCode(rt, ast.expr);
|
||||||
|
|
||||||
EMIT_BYTE(rt, code,TOY_OPCODE_MULTIPLY);
|
EMIT_BYTE(rt, code,TOY_OPCODE_MULTIPLY);
|
||||||
EMIT_BYTE(rt, code,TOY_OPCODE_ASSIGN); //squeezed
|
EMIT_BYTE(rt, code,TOY_OPCODE_ASSIGN); //squeezed
|
||||||
@@ -347,7 +393,7 @@ static void writeInstructionAssign(Toy_Routine** rt, Toy_AstVarAssign ast) {
|
|||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
|
|
||||||
writeRoutineCode(rt, ast.expr);
|
result += writeRoutineCode(rt, ast.expr);
|
||||||
|
|
||||||
EMIT_BYTE(rt, code,TOY_OPCODE_DIVIDE);
|
EMIT_BYTE(rt, code,TOY_OPCODE_DIVIDE);
|
||||||
EMIT_BYTE(rt, code,TOY_OPCODE_ASSIGN); //squeezed
|
EMIT_BYTE(rt, code,TOY_OPCODE_ASSIGN); //squeezed
|
||||||
@@ -365,7 +411,7 @@ static void writeInstructionAssign(Toy_Routine** rt, Toy_AstVarAssign ast) {
|
|||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
|
|
||||||
writeRoutineCode(rt, ast.expr);
|
result += writeRoutineCode(rt, ast.expr);
|
||||||
|
|
||||||
EMIT_BYTE(rt, code,TOY_OPCODE_MODULO);
|
EMIT_BYTE(rt, code,TOY_OPCODE_MODULO);
|
||||||
EMIT_BYTE(rt, code,TOY_OPCODE_ASSIGN); //squeezed
|
EMIT_BYTE(rt, code,TOY_OPCODE_ASSIGN); //squeezed
|
||||||
@@ -379,9 +425,11 @@ static void writeInstructionAssign(Toy_Routine** rt, Toy_AstVarAssign ast) {
|
|||||||
//4-byte alignment
|
//4-byte alignment
|
||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeInstructionAccess(Toy_Routine** rt, Toy_AstVarAccess ast) {
|
static unsigned int writeInstructionAccess(Toy_Routine** rt, Toy_AstVarAccess ast) {
|
||||||
//push the name
|
//push the name
|
||||||
EMIT_BYTE(rt, code, TOY_OPCODE_READ);
|
EMIT_BYTE(rt, code, TOY_OPCODE_READ);
|
||||||
EMIT_BYTE(rt, code, TOY_VALUE_STRING);
|
EMIT_BYTE(rt, code, TOY_VALUE_STRING);
|
||||||
@@ -395,6 +443,8 @@ static void writeInstructionAccess(Toy_Routine** rt, Toy_AstVarAccess ast) {
|
|||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
EMIT_BYTE(rt, code,0);
|
EMIT_BYTE(rt, code,0);
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//routine structure
|
//routine structure
|
||||||
@@ -402,11 +452,13 @@ static void writeInstructionAccess(Toy_Routine** rt, Toy_AstVarAccess ast) {
|
|||||||
// //
|
// //
|
||||||
// }
|
// }
|
||||||
|
|
||||||
static void writeRoutineCode(Toy_Routine** rt, Toy_Ast* ast) {
|
static unsigned int writeRoutineCode(Toy_Routine** rt, Toy_Ast* ast) {
|
||||||
if (ast == NULL) {
|
if (ast == NULL) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int result = 0;
|
||||||
|
|
||||||
//determine how to write each instruction based on the Ast
|
//determine how to write each instruction based on the Ast
|
||||||
switch(ast->type) {
|
switch(ast->type) {
|
||||||
case TOY_AST_BLOCK:
|
case TOY_AST_BLOCK:
|
||||||
@@ -417,8 +469,8 @@ static void writeRoutineCode(Toy_Routine** rt, Toy_Ast* ast) {
|
|||||||
EMIT_BYTE(rt, code, 0);
|
EMIT_BYTE(rt, code, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
writeRoutineCode(rt, ast->block.child);
|
result += writeRoutineCode(rt, ast->block.child);
|
||||||
writeRoutineCode(rt, ast->block.next);
|
result += writeRoutineCode(rt, ast->block.next);
|
||||||
|
|
||||||
if (ast->block.innerScope) {
|
if (ast->block.innerScope) {
|
||||||
EMIT_BYTE(rt, code, TOY_OPCODE_SCOPE_POP);
|
EMIT_BYTE(rt, code, TOY_OPCODE_SCOPE_POP);
|
||||||
@@ -429,39 +481,43 @@ static void writeRoutineCode(Toy_Routine** rt, Toy_Ast* ast) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TOY_AST_VALUE:
|
case TOY_AST_VALUE:
|
||||||
writeInstructionValue(rt, ast->value);
|
result += writeInstructionValue(rt, ast->value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOY_AST_UNARY:
|
case TOY_AST_UNARY:
|
||||||
writeInstructionUnary(rt, ast->unary);
|
result += writeInstructionUnary(rt, ast->unary);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOY_AST_BINARY:
|
case TOY_AST_BINARY:
|
||||||
writeInstructionBinary(rt, ast->binary);
|
result += writeInstructionBinary(rt, ast->binary);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOY_AST_COMPARE:
|
case TOY_AST_COMPARE:
|
||||||
writeInstructionCompare(rt, ast->compare);
|
result += writeInstructionCompare(rt, ast->compare);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOY_AST_GROUP:
|
case TOY_AST_GROUP:
|
||||||
writeInstructionGroup(rt, ast->group);
|
result += writeInstructionGroup(rt, ast->group);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TOY_AST_COMPOUND:
|
||||||
|
result += writeInstructionCompound(rt, ast->compound);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOY_AST_PRINT:
|
case TOY_AST_PRINT:
|
||||||
writeInstructionPrint(rt, ast->print);
|
result += writeInstructionPrint(rt, ast->print);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOY_AST_VAR_DECLARE:
|
case TOY_AST_VAR_DECLARE:
|
||||||
writeInstructionVarDeclare(rt, ast->varDeclare);
|
result += writeInstructionVarDeclare(rt, ast->varDeclare);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOY_AST_VAR_ASSIGN:
|
case TOY_AST_VAR_ASSIGN:
|
||||||
writeInstructionAssign(rt, ast->varAssign);
|
result += writeInstructionAssign(rt, ast->varAssign);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOY_AST_VAR_ACCESS:
|
case TOY_AST_VAR_ACCESS:
|
||||||
writeInstructionAccess(rt, ast->varAccess);
|
result += writeInstructionAccess(rt, ast->varAccess);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//meta instructions are disallowed
|
//meta instructions are disallowed
|
||||||
@@ -481,6 +537,8 @@ static void writeRoutineCode(Toy_Routine** rt, Toy_Ast* ast) {
|
|||||||
exit(-1);
|
exit(-1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* writeRoutine(Toy_Routine* rt, Toy_Ast* ast) {
|
static void* writeRoutine(Toy_Routine* rt, Toy_Ast* ast) {
|
||||||
|
|||||||
@@ -420,6 +420,74 @@ static void processConcat(Toy_VM* vm) {
|
|||||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_STRING(result));
|
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_STRING(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void processIndex(Toy_VM* vm) {
|
||||||
|
unsigned char count = READ_BYTE(vm); //value[index, length] ; 1[2, 3]
|
||||||
|
|
||||||
|
Toy_Value value = TOY_VALUE_FROM_NULL();
|
||||||
|
Toy_Value index = TOY_VALUE_FROM_NULL();
|
||||||
|
Toy_Value length = TOY_VALUE_FROM_NULL();
|
||||||
|
|
||||||
|
if (count == 3) {
|
||||||
|
length = Toy_popStack(&vm->stack);
|
||||||
|
index = Toy_popStack(&vm->stack);
|
||||||
|
value = Toy_popStack(&vm->stack);
|
||||||
|
}
|
||||||
|
else if (count == 2) {
|
||||||
|
index = Toy_popStack(&vm->stack);
|
||||||
|
value = Toy_popStack(&vm->stack);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Toy_error("Incorrect number of elements found in index");
|
||||||
|
//TODO: clear stack
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//process based on value's type
|
||||||
|
if (TOY_VALUE_IS_STRING(value)) {
|
||||||
|
//type checks
|
||||||
|
if (!TOY_VALUE_IS_INTEGER(index)) {
|
||||||
|
Toy_error("Failed to index a string");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(TOY_VALUE_IS_NULL(length) || TOY_VALUE_IS_INTEGER(length))) {
|
||||||
|
Toy_error("Failed to index-length a string");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//extract values
|
||||||
|
int i = TOY_VALUE_AS_INTEGER(index);
|
||||||
|
int l = TOY_VALUE_IS_INTEGER(length) ? TOY_VALUE_AS_INTEGER(length) : 1;
|
||||||
|
|
||||||
|
//extract string
|
||||||
|
Toy_String* str = TOY_VALUE_AS_STRING(value);
|
||||||
|
Toy_String* result = NULL;
|
||||||
|
|
||||||
|
//extract cstring, based on type
|
||||||
|
if (str->type == TOY_STRING_LEAF) {
|
||||||
|
const char* cstr = str->as.leaf.data;
|
||||||
|
result = Toy_createStringLength(&vm->stringBucket, cstr + i, l);
|
||||||
|
}
|
||||||
|
else if (str->type == TOY_STRING_NODE) {
|
||||||
|
char* cstr = Toy_getStringRawBuffer(str);
|
||||||
|
result = Toy_createStringLength(&vm->stringBucket, cstr + i, l);
|
||||||
|
free(cstr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Unknown string type found in processIndex, exiting\n" TOY_CC_RESET);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//finally
|
||||||
|
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_STRING(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Unknown value type %d found in processIndex, exiting\n" TOY_CC_RESET, value.type);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void process(Toy_VM* vm) {
|
static void process(Toy_VM* vm) {
|
||||||
while(true) {
|
while(true) {
|
||||||
Toy_OpcodeType opcode = READ_BYTE(vm);
|
Toy_OpcodeType opcode = READ_BYTE(vm);
|
||||||
@@ -494,6 +562,10 @@ static void process(Toy_VM* vm) {
|
|||||||
processConcat(vm);
|
processConcat(vm);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TOY_OPCODE_INDEX:
|
||||||
|
processIndex(vm);
|
||||||
|
break;
|
||||||
|
|
||||||
case TOY_OPCODE_PASS:
|
case TOY_OPCODE_PASS:
|
||||||
case TOY_OPCODE_ERROR:
|
case TOY_OPCODE_ERROR:
|
||||||
case TOY_OPCODE_EOF:
|
case TOY_OPCODE_EOF:
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ int test_sizeof_ast_64bit() {
|
|||||||
TEST_SIZEOF(Toy_AstBinary, 24);
|
TEST_SIZEOF(Toy_AstBinary, 24);
|
||||||
TEST_SIZEOF(Toy_AstCompare, 24);
|
TEST_SIZEOF(Toy_AstCompare, 24);
|
||||||
TEST_SIZEOF(Toy_AstGroup, 16);
|
TEST_SIZEOF(Toy_AstGroup, 16);
|
||||||
|
TEST_SIZEOF(Toy_AstCompound, 24);
|
||||||
TEST_SIZEOF(Toy_AstPrint, 16);
|
TEST_SIZEOF(Toy_AstPrint, 16);
|
||||||
TEST_SIZEOF(Toy_AstVarDeclare, 24);
|
TEST_SIZEOF(Toy_AstVarDeclare, 24);
|
||||||
TEST_SIZEOF(Toy_AstVarAssign, 24);
|
TEST_SIZEOF(Toy_AstVarAssign, 24);
|
||||||
@@ -54,6 +55,7 @@ int test_sizeof_ast_32bit() {
|
|||||||
TEST_SIZEOF(Toy_AstBinary, 16);
|
TEST_SIZEOF(Toy_AstBinary, 16);
|
||||||
TEST_SIZEOF(Toy_AstCompare, 16);
|
TEST_SIZEOF(Toy_AstCompare, 16);
|
||||||
TEST_SIZEOF(Toy_AstGroup, 8);
|
TEST_SIZEOF(Toy_AstGroup, 8);
|
||||||
|
TEST_SIZEOF(Toy_AstCompound, 16);
|
||||||
TEST_SIZEOF(Toy_AstPrint, 8);
|
TEST_SIZEOF(Toy_AstPrint, 8);
|
||||||
TEST_SIZEOF(Toy_AstVarDeclare, 12);
|
TEST_SIZEOF(Toy_AstVarDeclare, 12);
|
||||||
TEST_SIZEOF(Toy_AstVarAssign, 16);
|
TEST_SIZEOF(Toy_AstVarAssign, 16);
|
||||||
|
|||||||
@@ -13,6 +13,11 @@ print "Hello" .. "world!";
|
|||||||
//print with escaped characters
|
//print with escaped characters
|
||||||
print "\tHello\nworld";
|
print "\tHello\nworld";
|
||||||
|
|
||||||
|
//print from a leaf string
|
||||||
|
print "Hello world"[0,5];
|
||||||
|
|
||||||
|
print ("hello" .. "world")[2,6];
|
||||||
|
|
||||||
//TODO: in the repl, -s to supress output, or -d to print debugging info
|
//TODO: in the repl, -s to supress output, or -d to print debugging info
|
||||||
|
|
||||||
//TODO: the `assert` keyword will be useful for these
|
//TODO: the `assert` keyword will be useful for these
|
||||||
|
|||||||
Reference in New Issue
Block a user