Skip to content

Commit

Permalink
Implemented assert keyword, read more
Browse files Browse the repository at this point in the history
The assert keyword works, but I want to add a cmd option to suppress or
disable the errors.

The tests need some serious TLC. I know that, but I'm kicking it down
the road for now.
  • Loading branch information
Ratstail91 committed Nov 9, 2024
1 parent 1925d41 commit 1608a13
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 69 deletions.
10 changes: 10 additions & 0 deletions source/toy_ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,16 @@ void Toy_private_emitAstCompound(Toy_Bucket** bucketHandle, Toy_Ast** astHandle,
(*astHandle) = tmp;
}

void Toy_private_emitAstAssert(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* child, Toy_Ast* msg) {
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast));

tmp->type = TOY_AST_ASSERT;
tmp->assert.child = child;
tmp->assert.message = msg;

(*astHandle) = tmp;
}

void Toy_private_emitAstPrint(Toy_Bucket** bucketHandle, Toy_Ast** astHandle) {
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast));

Expand Down
9 changes: 9 additions & 0 deletions source/toy_ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ typedef enum Toy_AstType {
TOY_AST_GROUP,
TOY_AST_COMPOUND,

TOY_AST_ASSERT,
TOY_AST_PRINT,

TOY_AST_VAR_DECLARE,
Expand Down Expand Up @@ -116,6 +117,12 @@ typedef struct Toy_AstCompound {
Toy_Ast* right;
} Toy_AstCompound;

typedef struct Toy_AstAssert {
Toy_AstType type;
Toy_Ast* child;
Toy_Ast* message;
} Toy_AstAssert;

typedef struct Toy_AstPrint {
Toy_AstType type;
Toy_Ast* child;
Expand Down Expand Up @@ -160,6 +167,7 @@ union Toy_Ast { //32 | 64 BITNESS
Toy_AstCompare compare; //16 | 24
Toy_AstGroup group; //8 | 16
Toy_AstCompound compound; //16 | 24
Toy_AstAssert assert; //16 | 24
Toy_AstPrint print; //8 | 16
Toy_AstVarDeclare varDeclare; //16 | 24
Toy_AstVarAssign varAssign; //16 | 24
Expand All @@ -179,6 +187,7 @@ void Toy_private_emitAstCompare(Toy_Bucket** bucketHandle, Toy_Ast** astHandle,T
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_emitAstAssert(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* child, Toy_Ast* msg);
void Toy_private_emitAstPrint(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);

void Toy_private_emitAstVariableDeclaration(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_String* name, Toy_Ast* expr);
Expand Down
1 change: 1 addition & 0 deletions source/toy_opcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ typedef enum Toy_OpcodeType {
TOY_OPCODE_SCOPE_POP,

//various action instructions
TOY_OPCODE_ASSERT,
TOY_OPCODE_PRINT,
TOY_OPCODE_CONCAT,
TOY_OPCODE_INDEX,
Expand Down
29 changes: 24 additions & 5 deletions source/toy_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ static ParsingTuple parsingRulesetTable[] = {
//structural operators
{PREC_NONE,group,NULL},// TOY_TOKEN_OPERATOR_PAREN_LEFT,
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_PAREN_RIGHT,
{PREC_CALL,NULL,compound},// TOY_TOKEN_OPERATOR_BRACKET_LEFT,
{PREC_GROUP,NULL,compound},// TOY_TOKEN_OPERATOR_BRACKET_LEFT,
{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_RIGHT,
Expand All @@ -208,7 +208,7 @@ static ParsingTuple parsingRulesetTable[] = {
{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_COLON,

{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_SEMICOLON, // ;
{PREC_CALL,NULL,compound},// TOY_TOKEN_OPERATOR_COMMA, // ,
{PREC_GROUP,NULL,compound},// TOY_TOKEN_OPERATOR_COMMA, // ,

{PREC_NONE,NULL,NULL},// TOY_TOKEN_OPERATOR_DOT, // .
{PREC_CALL,NULL,binary},// TOY_TOKEN_OPERATOR_CONCAT, // ..
Expand Down Expand Up @@ -563,11 +563,11 @@ static Toy_AstFlag compound(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_A
advance(parser);

if (parser->previous.type == TOY_TOKEN_OPERATOR_COMMA) {
parsePrecedence(bucketHandle, parser, rootHandle, PREC_ASSIGNMENT + 1);
parsePrecedence(bucketHandle, parser, rootHandle, PREC_GROUP);
return TOY_AST_FLAG_COMPOUND_COLLECTION;
}
else if (parser->previous.type == TOY_TOKEN_OPERATOR_BRACKET_LEFT) {
parsePrecedence(bucketHandle, parser, rootHandle, PREC_ASSIGNMENT + 1);
parsePrecedence(bucketHandle, parser, rootHandle, PREC_GROUP);
consume(parser, TOY_TOKEN_OPERATOR_BRACKET_RIGHT, "Expected ']' at the end of index expression");
return TOY_AST_FLAG_COMPOUND_INDEX;
}
Expand Down Expand Up @@ -655,6 +655,21 @@ static void makeExpr(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** ro
//forward declarations
static void makeBlockStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);

static void makeAssertStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
Toy_Ast* ast = NULL; //assert's emit function is a bit different
makeExpr(bucketHandle, parser, &ast);

//NOTE: if it's a compound, then it's got a second arg
if (ast->type == TOY_AST_COMPOUND) {
Toy_private_emitAstAssert(bucketHandle, rootHandle, ast->compound.left, ast->compound.right);
}
else {
Toy_private_emitAstAssert(bucketHandle, rootHandle, ast, NULL);
}

consume(parser, TOY_TOKEN_OPERATOR_SEMICOLON, "Expected ';' at the end of assert statement");
}

static void makePrintStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
makeExpr(bucketHandle, parser, rootHandle);
Toy_private_emitAstPrint(bucketHandle, rootHandle);
Expand Down Expand Up @@ -715,7 +730,11 @@ static void makeStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** ro
return;
}

//assert
else if (match(parser, TOY_TOKEN_KEYWORD_ASSERT)) {
makeAssertStmt(bucketHandle, parser, rootHandle);
return;
}

//if-then-else
//while-then
//for-pre-clause-post-then
Expand Down
20 changes: 20 additions & 0 deletions source/toy_routine.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,22 @@ static unsigned int writeInstructionCompound(Toy_Routine** rt, Toy_AstCompound a
}
}

static unsigned int writeInstructionAssert(Toy_Routine** rt, Toy_AstAssert ast) {
//the thing to print
writeRoutineCode(rt, ast.child);
writeRoutineCode(rt, ast.message);

//output the print opcode
EMIT_BYTE(rt, code, TOY_OPCODE_ASSERT);

//4-byte alignment
EMIT_BYTE(rt, code, ast.message != NULL ? 2 : 1); //arg count
EMIT_BYTE(rt, code,0);
EMIT_BYTE(rt, code,0);

return 0;
}

static unsigned int writeInstructionPrint(Toy_Routine** rt, Toy_AstPrint ast) {
//the thing to print
writeRoutineCode(rt, ast.child);
Expand Down Expand Up @@ -504,6 +520,10 @@ static unsigned int writeRoutineCode(Toy_Routine** rt, Toy_Ast* ast) {
result += writeInstructionCompound(rt, ast->compound);
break;

case TOY_AST_ASSERT:
result += writeInstructionAssert(rt, ast->assert);
break;

case TOY_AST_PRINT:
result += writeInstructionPrint(rt, ast->print);
break;
Expand Down
84 changes: 71 additions & 13 deletions source/toy_value.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
#include "toy_console_colors.h"

#include "toy_string.h"
#include "toy_print.h"

#include <stdio.h>
#include <stdlib.h>

//utils
static unsigned int hashUInt(unsigned int x) {
Expand Down Expand Up @@ -37,10 +39,10 @@ unsigned int Toy_hashValue(Toy_Value value) {
case TOY_VALUE_TYPE:
case TOY_VALUE_ANY:
case TOY_VALUE_UNKNOWN:
break;
fprintf(stderr, TOY_CC_ERROR "ERROR: Can't hash an unknown value type, exiting\n" TOY_CC_RESET);
exit(-1);
}

Toy_error(TOY_CC_ERROR "ERROR: Can't hash an unknown value type\n" TOY_CC_RESET);
return 0;
}

Expand All @@ -64,11 +66,11 @@ Toy_Value Toy_copyValue(Toy_Value value) {
case TOY_VALUE_TYPE:
case TOY_VALUE_ANY:
case TOY_VALUE_UNKNOWN:
break;
fprintf(stderr, TOY_CC_ERROR "ERROR: Can't copy an unknown value type, exiting\n" TOY_CC_RESET);
exit(-1);
}

//dummy return
Toy_error(TOY_CC_ERROR "ERROR: Can't copy an unknown value type\n" TOY_CC_RESET);
return TOY_VALUE_FROM_NULL();
}

Expand All @@ -93,14 +95,15 @@ void Toy_freeValue(Toy_Value value) {
case TOY_VALUE_TYPE:
case TOY_VALUE_ANY:
case TOY_VALUE_UNKNOWN:
Toy_error(TOY_CC_ERROR "ERROR: Can't free an unknown type\n" TOY_CC_RESET);
fprintf(stderr, TOY_CC_ERROR "ERROR: Can't free an unknown value type, exiting\n" TOY_CC_RESET);
exit(-1);
}
}

bool Toy_checkValueIsTruthy(Toy_Value value) {
//null is an error
if (TOY_VALUE_IS_NULL(value)) {
Toy_error(TOY_CC_ERROR "ERROR: 'null' is neither true nor false\n" TOY_CC_RESET);
Toy_error("'null' is neither true nor false");
return false;
}

Expand Down Expand Up @@ -158,10 +161,10 @@ bool Toy_checkValuesAreEqual(Toy_Value left, Toy_Value right) {
case TOY_VALUE_TYPE:
case TOY_VALUE_ANY:
case TOY_VALUE_UNKNOWN:
break;
fprintf(stderr, TOY_CC_ERROR "ERROR: Unknown types in value equality, exiting\n" TOY_CC_RESET);
exit(-1);
}

Toy_error(TOY_CC_ERROR "ERROR: Unknown types in value equality\n" TOY_CC_RESET);
return false;
}

Expand All @@ -187,10 +190,10 @@ bool Toy_checkValuesAreComparable(Toy_Value left, Toy_Value right) {
case TOY_VALUE_TYPE:
case TOY_VALUE_ANY:
case TOY_VALUE_UNKNOWN:
break;
fprintf(stderr, TOY_CC_ERROR "Unknown types in value comparison check, exiting\n" TOY_CC_RESET);
exit(-1);
}

Toy_error(TOY_CC_ERROR "ERROR: Unknown types in value comparison check\n" TOY_CC_RESET);
return false;
}

Expand Down Expand Up @@ -235,9 +238,64 @@ int Toy_compareValues(Toy_Value left, Toy_Value right) {
case TOY_VALUE_TYPE:
case TOY_VALUE_ANY:
case TOY_VALUE_UNKNOWN:
break;
fprintf(stderr, TOY_CC_ERROR "Unknown types in value comparison, exiting\n" TOY_CC_RESET);
exit(-1);
}

Toy_error(TOY_CC_ERROR "ERROR: Unknown types in value comparison\n" TOY_CC_RESET);
return -1;
}

void Toy_stringifyValue(Toy_Value value, Toy_callbackType callback) {
//NOTE: don't append a newline
switch(value.type) {
case TOY_VALUE_NULL:
callback("null");
break;

case TOY_VALUE_BOOLEAN:
callback(TOY_VALUE_AS_BOOLEAN(value) ? "true" : "false");
break;

case TOY_VALUE_INTEGER: {
char buffer[16];
sprintf(buffer, "%d", TOY_VALUE_AS_INTEGER(value));
callback(buffer);
break;
}

case TOY_VALUE_FLOAT: {
char buffer[16];
sprintf(buffer, "%f", TOY_VALUE_AS_FLOAT(value));
callback(buffer);
break;
}

case TOY_VALUE_STRING: {
Toy_String* str = TOY_VALUE_AS_STRING(value);

//TODO: decide on how long strings, etc. live for in memory
if (str->type == TOY_STRING_NODE) {
char* buffer = Toy_getStringRawBuffer(str);
callback(buffer);
free(buffer);
}
else if (str->type == TOY_STRING_LEAF) {
callback(str->as.leaf.data);
}
else if (str->type == TOY_STRING_NAME) {
callback(str->as.name.data); //should this be a thing?
}
break;
}

case TOY_VALUE_ARRAY:
case TOY_VALUE_TABLE:
case TOY_VALUE_FUNCTION:
case TOY_VALUE_OPAQUE:
case TOY_VALUE_TYPE:
case TOY_VALUE_ANY:
case TOY_VALUE_UNKNOWN:
fprintf(stderr, TOY_CC_ERROR "Unknown types in value stringify, exiting\n" TOY_CC_RESET);
exit(-1);
}
}
4 changes: 4 additions & 0 deletions source/toy_value.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "toy_common.h"
#include "toy_print.h"

//forward declarations
struct Toy_String;
Expand Down Expand Up @@ -67,3 +68,6 @@ TOY_API bool Toy_checkValueIsTruthy(Toy_Value value);
TOY_API bool Toy_checkValuesAreEqual(Toy_Value left, Toy_Value right);
TOY_API bool Toy_checkValuesAreComparable(Toy_Value left, Toy_Value right);
TOY_API int Toy_compareValues(Toy_Value left, Toy_Value right);

//convert the value to a string, then forward it to a callback
TOY_API void Toy_stringifyValue(Toy_Value value, Toy_callbackType callback);
Loading

0 comments on commit 1608a13

Please sign in to comment.