Skip to content

Commit

Permalink
Added simple assignment, read more
Browse files Browse the repository at this point in the history
I was coding earlier this week, but my brain was so foggy I ended up not
knowing what I was doing. After a few days break, I've cleaned up the
mess, which took hours.

Changes:
* Variables can be assigned
* Added new value types as placeholders
* Added 'compare' and 'assign' to the AST
* Added duplicate opcode
* Added functions to copy and free values
* Max name length is 255 chars
* Compound assigns are squeezed into one word

To be completed:

* Tests for this commit's changes
* Compound assignments
* Variable access
  • Loading branch information
Ratstail91 committed Oct 25, 2024
1 parent 5b17c5e commit 3148a56
Show file tree
Hide file tree
Showing 17 changed files with 654 additions and 183 deletions.
28 changes: 28 additions & 0 deletions .notes/read-opcode-layout.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
TOY_OPCODE_DECLARE:
{Declare, type, length, 0} ; {emitString()}

# write value
TOY_OPCODE_READ:
null -> {Read, type, 0, 0}
bool -> {Read, type, value, 0}
int -> {Read, type, 0, 0} ; {value}
float -> {Read, type, 0, 0} ; {value}
string -> {Read, type, leaf, 0} ; {emitString()}

# write assignment
TOY_AST_FLAG_ASSIGN:
{Read, type(string), name, length} ;
{emitString()} ;
{writeCode()} ;
{Assign, 0, 0, 0} ;

TOY_AST_FLAG_ADD_ASSIGN:
{Read, type(string), name, length} ;
{emitString()} ;
{Duplicate, 0, 0, 0} ;
{writeCode()} ;
{Assign, 0, 0, 0}
{Add, Assign, 0, 0} ;

//subtract, multiply, divide, modulo all mimic add

5 changes: 4 additions & 1 deletion makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ repl: source

#various kinds of available tests
.PHONY: tests
tests: clean test-cases test-integrations test-benchmarks
tests: clean test-cases

.PHONY: test-all
test-all: clean test-cases test-integrations test-benchmarks

.PHONY: test-cases
test-cases:
Expand Down
22 changes: 8 additions & 14 deletions repl/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,18 +263,6 @@ int repl(const char* filepath) {
//free the bytecode, and leave the VM ready for the next loop
Toy_resetVM(&vm);

//count the bucket memory - hang on, this this garbage collection??
Toy_Bucket* iter = bucket;
int depth = 0;
while (iter->next) {
iter = iter->next;
if (++depth >= 7) {
Toy_freeBucket(&bucket);
bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
break;
}
}

printf("%s> ", prompt); //shows the terminal prompt
}

Expand Down Expand Up @@ -331,9 +319,12 @@ static void debugStackPrint(Toy_Stack* stack) {
}

case TOY_VALUE_ARRAY:
case TOY_VALUE_DICTIONARY:
case TOY_VALUE_TABLE:
case TOY_VALUE_FUNCTION:
case TOY_VALUE_OPAQUE:
case TOY_VALUE_TYPE:
case TOY_VALUE_ANY:
case TOY_VALUE_UNKNOWN:
printf("???");
break;
}
Expand Down Expand Up @@ -393,9 +384,12 @@ static void debugScopePrint(Toy_Scope* scope, int depth) {
}

case TOY_VALUE_ARRAY:
case TOY_VALUE_DICTIONARY:
case TOY_VALUE_TABLE:
case TOY_VALUE_FUNCTION:
case TOY_VALUE_OPAQUE:
case TOY_VALUE_TYPE:
case TOY_VALUE_ANY:
case TOY_VALUE_UNKNOWN:
printf("???");
break;
}
Expand Down
22 changes: 22 additions & 0 deletions source/toy_ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ void Toy_private_emitAstBinary(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, T
(*astHandle) = tmp;
}

void Toy_private_emitAstCompare(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_COMPARE;
tmp->compare.flag = flag;
tmp->compare.left = *astHandle; //left-recursive
tmp->compare.right = right;

(*astHandle) = tmp;
}

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

Expand Down Expand Up @@ -91,6 +102,17 @@ void Toy_private_emitAstVariableDeclaration(Toy_Bucket** bucketHandle, Toy_Ast**
(*astHandle) = tmp;
}

void Toy_private_emitAstVariableAssignment(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_String* name, Toy_AstFlag flag, Toy_Ast* expr) {
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast));

tmp->type = TOY_AST_VAR_ASSIGN;
tmp->varAssign.flag = flag;
tmp->varAssign.name = name;
tmp->varAssign.expr = expr;

(*astHandle) = tmp;
}

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

Expand Down
71 changes: 47 additions & 24 deletions source/toy_ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ typedef enum Toy_AstType {
TOY_AST_VALUE,
TOY_AST_UNARY,
TOY_AST_BINARY,
TOY_AST_COMPARE,
TOY_AST_GROUP,

TOY_AST_PRINT,

TOY_AST_VAR_DECLARE,
TOY_AST_VAR_ASSIGN,

TOY_AST_PASS,
TOY_AST_ERROR,
Expand All @@ -26,34 +28,37 @@ typedef enum Toy_AstType {

//flags are handled differently by different types
typedef enum Toy_AstFlag {
TOY_AST_FLAG_NONE,
TOY_AST_FLAG_NONE = 0,

//binary flags
TOY_AST_FLAG_ADD,
TOY_AST_FLAG_SUBTRACT,
TOY_AST_FLAG_MULTIPLY,
TOY_AST_FLAG_DIVIDE,
TOY_AST_FLAG_MODULO,
TOY_AST_FLAG_ASSIGN,
TOY_AST_FLAG_ADD_ASSIGN,
TOY_AST_FLAG_SUBTRACT_ASSIGN,
TOY_AST_FLAG_MULTIPLY_ASSIGN,
TOY_AST_FLAG_DIVIDE_ASSIGN,
TOY_AST_FLAG_MODULO_ASSIGN,
TOY_AST_FLAG_COMPARE_EQUAL,
TOY_AST_FLAG_COMPARE_NOT,
TOY_AST_FLAG_COMPARE_LESS,
TOY_AST_FLAG_COMPARE_LESS_EQUAL,
TOY_AST_FLAG_COMPARE_GREATER,
TOY_AST_FLAG_COMPARE_GREATER_EQUAL,
TOY_AST_FLAG_AND,
TOY_AST_FLAG_OR,
TOY_AST_FLAG_CONCAT,
TOY_AST_FLAG_ADD = 1,
TOY_AST_FLAG_SUBTRACT = 2,
TOY_AST_FLAG_MULTIPLY = 3,
TOY_AST_FLAG_DIVIDE = 4,
TOY_AST_FLAG_MODULO = 5,

TOY_AST_FLAG_ASSIGN = 10,
TOY_AST_FLAG_ADD_ASSIGN = 11,
TOY_AST_FLAG_SUBTRACT_ASSIGN = 12,
TOY_AST_FLAG_MULTIPLY_ASSIGN = 13,
TOY_AST_FLAG_DIVIDE_ASSIGN = 14,
TOY_AST_FLAG_MODULO_ASSIGN = 15,

TOY_AST_FLAG_COMPARE_EQUAL = 20,
TOY_AST_FLAG_COMPARE_NOT = 21,
TOY_AST_FLAG_COMPARE_LESS = 22,
TOY_AST_FLAG_COMPARE_LESS_EQUAL = 23,
TOY_AST_FLAG_COMPARE_GREATER = 24,
TOY_AST_FLAG_COMPARE_GREATER_EQUAL = 25,

TOY_AST_FLAG_AND = 30,
TOY_AST_FLAG_OR = 31,
TOY_AST_FLAG_CONCAT = 32,

//unary flags
TOY_AST_FLAG_NEGATE,
TOY_AST_FLAG_INCREMENT,
TOY_AST_FLAG_DECREMENT,
TOY_AST_FLAG_NEGATE = 33,
TOY_AST_FLAG_INCREMENT = 34,
TOY_AST_FLAG_DECREMENT = 35,

// TOY_AST_FLAG_TERNARY,
} Toy_AstFlag;
Expand Down Expand Up @@ -86,6 +91,13 @@ typedef struct Toy_AstBinary {
Toy_Ast* right;
} Toy_AstBinary;

typedef struct Toy_AstCompare {
Toy_AstType type;
Toy_AstFlag flag;
Toy_Ast* left;
Toy_Ast* right;
} Toy_AstCompare;

typedef struct Toy_AstGroup {
Toy_AstType type;
Toy_Ast* child;
Expand All @@ -102,6 +114,13 @@ typedef struct Toy_AstVarDeclare {
Toy_Ast* expr;
} Toy_AstVarDeclare;

typedef struct Toy_AstVarAssign {
Toy_AstType type;
Toy_AstFlag flag;
Toy_String* name;
Toy_Ast* expr;
} Toy_AstVarAssign;

typedef struct Toy_AstPass {
Toy_AstType type;
} Toy_AstPass;
Expand All @@ -120,9 +139,11 @@ union Toy_Ast { //32 | 64 BITNESS
Toy_AstValue value; //12 | 24
Toy_AstUnary unary; //12 | 16
Toy_AstBinary binary; //16 | 24
Toy_AstCompare compare; //16 | 24
Toy_AstGroup group; //8 | 16
Toy_AstPrint print; //8 | 16
Toy_AstVarDeclare varDeclare; //16 | 24
Toy_AstVarAssign varAssign; //16 | 24
Toy_AstPass pass; //4 | 4
Toy_AstError error; //4 | 4
Toy_AstEnd end; //4 | 4
Expand All @@ -134,11 +155,13 @@ void Toy_private_appendAstBlock(Toy_Bucket** bucketHandle, Toy_Ast* block, Toy_A
void Toy_private_emitAstValue(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Value value);
void Toy_private_emitAstUnary(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_AstFlag flag);
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_emitAstGroup(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);

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);
void Toy_private_emitAstVariableAssignment(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_String* name, Toy_AstFlag flag, Toy_Ast* expr);

void Toy_private_emitAstPass(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);
void Toy_private_emitAstError(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);
Expand Down
2 changes: 2 additions & 0 deletions source/toy_opcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ typedef enum Toy_OpcodeType {
TOY_OPCODE_ASSIGN,
TOY_OPCODE_ACCESS,

TOY_OPCODE_DUPLICATE, //duplicate the top of the stack

//arithmetic instructions
TOY_OPCODE_ADD,
TOY_OPCODE_SUBTRACT,
Expand Down
62 changes: 56 additions & 6 deletions source/toy_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ typedef struct ParsingTuple {

static void parsePrecedence(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle, ParsingPrecedence precRule);

static Toy_AstFlag nameString(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
static Toy_AstFlag literal(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);
Expand All @@ -119,8 +120,8 @@ static Toy_AstFlag group(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast*
static ParsingTuple parsingRulesetTable[] = {
{PREC_PRIMARY,literal,NULL},// TOY_TOKEN_NULL,

//variable names
{PREC_NONE,NULL,NULL},// TOY_TOKEN_NAME,
//variable names (initially handled as a string)
{PREC_NONE,nameString,NULL},// TOY_TOKEN_NAME,

//types
{PREC_NONE,NULL,NULL},// TOY_TOKEN_TYPE_TYPE,
Expand Down Expand Up @@ -221,6 +222,44 @@ static ParsingTuple parsingRulesetTable[] = {
{PREC_NONE,NULL,NULL},// TOY_TOKEN_EOF,
};

static Toy_AstFlag nameString(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
Toy_String* name = Toy_createNameStringLength(bucketHandle, parser->previous.lexeme, parser->previous.length, TOY_VALUE_UNKNOWN);

Toy_AstFlag flag = TOY_AST_FLAG_NONE;

if (match(parser, TOY_TOKEN_OPERATOR_ASSIGN)) {
flag = TOY_AST_FLAG_ASSIGN;
}
else if (match(parser, TOY_TOKEN_OPERATOR_ADD_ASSIGN)) {
flag = TOY_AST_FLAG_ADD_ASSIGN;
}
else if (match(parser, TOY_TOKEN_OPERATOR_SUBTRACT_ASSIGN)) {
flag = TOY_AST_FLAG_SUBTRACT_ASSIGN;
}
else if (match(parser, TOY_TOKEN_OPERATOR_MULTIPLY_ASSIGN)) {
flag = TOY_AST_FLAG_MULTIPLY_ASSIGN;
}
else if (match(parser, TOY_TOKEN_OPERATOR_DIVIDE_ASSIGN)) {
flag = TOY_AST_FLAG_DIVIDE_ASSIGN;
}
else if (match(parser, TOY_TOKEN_OPERATOR_MODULO_ASSIGN)) {
flag = TOY_AST_FLAG_MODULO_ASSIGN;
}

//assignment
if (flag != TOY_AST_FLAG_NONE) {
Toy_Ast* expr = NULL;
parsePrecedence(bucketHandle, parser, &expr, PREC_ASSIGNMENT); //this makes chained assignment possible, I think
Toy_private_emitAstVariableAssignment(bucketHandle, rootHandle, name, flag, expr);
return TOY_AST_FLAG_NONE;
}

//access
printError(parser, parser->previous, "Unexpectedly found a variable access; this is not yet implemented");
Toy_private_emitAstError(bucketHandle, rootHandle);
return TOY_AST_FLAG_NONE;
}

static Toy_AstFlag literal(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
switch(parser->previous.type) {
case TOY_TOKEN_NULL:
Expand Down Expand Up @@ -494,6 +533,9 @@ static void parsePrecedence(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_A
return;
}

//grab this for name storage
Toy_Token prevToken = parser->previous;

Toy_Ast* ptr = NULL;
Toy_AstFlag flag = infix(bucketHandle, parser, &ptr);

Expand All @@ -502,8 +544,16 @@ static void parsePrecedence(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_A
(*rootHandle) = ptr;
return;
}

Toy_private_emitAstBinary(bucketHandle, rootHandle, flag, ptr);
else if (flag >= 10 && flag <= 19) {
Toy_String* name = Toy_createNameStringLength(bucketHandle, prevToken.lexeme, prevToken.length, TOY_VALUE_UNKNOWN);
Toy_private_emitAstVariableAssignment(bucketHandle, rootHandle, name, flag, ptr);
}
else if (flag >= 20 && flag <= 29) {
Toy_private_emitAstCompare(bucketHandle, rootHandle, flag, ptr);
}
else {
Toy_private_emitAstBinary(bucketHandle, rootHandle, flag, ptr);
}
}

//can't assign below a certain precedence
Expand Down Expand Up @@ -531,8 +581,8 @@ static void makeExprStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast*
static void makeVariableDeclarationStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
consume(parser, TOY_TOKEN_NAME, "Expected variable name after 'var' keyword");

if (parser->previous.length > 256) {
printError(parser, parser->previous, "Can't have a variable name longer than 256 characters");
if (parser->previous.length > 255) {
printError(parser, parser->previous, "Can't have a variable name longer than 255 characters");
Toy_private_emitAstError(bucketHandle, rootHandle);
return;
}
Expand Down
Loading

0 comments on commit 3148a56

Please sign in to comment.