mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 23:04:08 +10:00
Type checking in place
This commit is contained in:
@@ -1 +1,4 @@
|
|||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ static bool execVarDecl(Interpreter* interpreter, bool lng) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!setScopeVariable(interpreter->scope, identifier, parseIdentifierToValue(interpreter, popLiteralArray(&interpreter->stack)) )) {
|
if (!setScopeVariable(interpreter->scope, identifier, parseIdentifierToValue(interpreter, popLiteralArray(&interpreter->stack)), false)) {
|
||||||
printf("Incorrect type assigned to variable \"");
|
printf("Incorrect type assigned to variable \"");
|
||||||
printLiteral(identifier);
|
printLiteral(identifier);
|
||||||
printf("\"\n");
|
printf("\"\n");
|
||||||
@@ -338,7 +338,7 @@ static bool execVarAssign(Interpreter* interpreter) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!setScopeVariable(interpreter->scope, lhs, rhs)) {
|
if (!setScopeVariable(interpreter->scope, lhs, rhs, true)) {
|
||||||
printf("Incorrect type assigned to variable \"");
|
printf("Incorrect type assigned to variable \"");
|
||||||
printLiteral(lhs);
|
printLiteral(lhs);
|
||||||
printf("\"\n");
|
printf("\"\n");
|
||||||
|
|||||||
@@ -21,6 +21,58 @@ static void freeAncestorChain(Scope* scope) {
|
|||||||
FREE(Scope, scope);
|
FREE(Scope, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//return false if invalid type
|
||||||
|
static bool checkType(Literal typeLiteral, Literal value) {
|
||||||
|
//for any types
|
||||||
|
if (AS_TYPE(typeLiteral).mask == MASK_ANY) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//for each type, if a mismatch is found, return false
|
||||||
|
if ((AS_TYPE(typeLiteral).mask & MASK_BOOLEAN) && !IS_BOOLEAN(value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((AS_TYPE(typeLiteral).mask & MASK_INTEGER) && !IS_INTEGER(value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((AS_TYPE(typeLiteral).mask & MASK_FLOAT) && !IS_FLOAT(value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((AS_TYPE(typeLiteral).mask & MASK_STRING) && !IS_STRING(value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((AS_TYPE(typeLiteral).mask & MASK_ARRAY) && IS_ARRAY(value)) {
|
||||||
|
//check children
|
||||||
|
for (int i = 0; i < AS_ARRAY(value)->count; i++) {
|
||||||
|
if (!checkType(((Literal*)(AS_TYPE(typeLiteral).subtypes))[0], AS_ARRAY(value)->literals[i])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((AS_TYPE(typeLiteral).mask & MASK_DICTIONARY) && IS_DICTIONARY(value)) {
|
||||||
|
//check children
|
||||||
|
for (int i = 0; i < AS_DICTIONARY(value)->capacity; i++) {
|
||||||
|
//only assigned and non-tombstoned keys
|
||||||
|
if (!IS_NULL(AS_DICTIONARY(value)->entries[i].key)) {
|
||||||
|
if (checkType(((Literal*)(AS_TYPE(typeLiteral).subtypes))[0], AS_DICTIONARY(value)->entries[i].key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkType(((Literal*)(AS_TYPE(typeLiteral).subtypes))[1], AS_DICTIONARY(value)->entries[i].value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//exposed functions
|
//exposed functions
|
||||||
Scope* pushScope(Scope* ancestor) {
|
Scope* pushScope(Scope* ancestor) {
|
||||||
Scope* scope = ALLOCATE(Scope, 1);
|
Scope* scope = ALLOCATE(Scope, 1);
|
||||||
@@ -44,7 +96,7 @@ Scope* popScope(Scope* scope) {
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#include <stdio.h>
|
|
||||||
//returns false if error
|
//returns false if error
|
||||||
bool declareScopeVariable(Scope* scope, Literal key, Literal type) {
|
bool declareScopeVariable(Scope* scope, Literal key, Literal type) {
|
||||||
//don't redefine a variable within this scope
|
//don't redefine a variable within this scope
|
||||||
@@ -64,19 +116,30 @@ bool isDelcaredScopeVariable(Scope* scope, Literal key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//return false if undefined, or can't be assigned
|
//return false if undefined, or can't be assigned
|
||||||
bool setScopeVariable(Scope* scope, Literal key, Literal value) {
|
bool setScopeVariable(Scope* scope, Literal key, Literal value, bool constCheck) {
|
||||||
//dead end
|
//dead end
|
||||||
if (scope == NULL) {
|
if (scope == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: type checking
|
|
||||||
|
|
||||||
//if it's not in this scope, keep searching up the chain
|
//if it's not in this scope, keep searching up the chain
|
||||||
if (!existsLiteralDictionary(&scope->variables, key)) {
|
if (!existsLiteralDictionary(&scope->variables, key)) {
|
||||||
return setScopeVariable(scope->ancestor, key, value);
|
return setScopeVariable(scope->ancestor, key, value, constCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//type checking
|
||||||
|
Literal typeLiteral = getLiteralDictionary(&scope->types, key);
|
||||||
|
|
||||||
|
if (!checkType(typeLiteral, value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//const check
|
||||||
|
if (constCheck && (AS_TYPE(typeLiteral).mask & MASK_CONST)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//actually assign
|
||||||
setLiteralDictionary(&scope->variables, key, value);
|
setLiteralDictionary(&scope->variables, key, value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "literal_array.h"
|
||||||
#include "literal_dictionary.h"
|
#include "literal_dictionary.h"
|
||||||
|
|
||||||
typedef struct Scope {
|
typedef struct Scope {
|
||||||
@@ -17,6 +18,6 @@ bool declareScopeVariable(Scope* scope, Literal key, Literal type);
|
|||||||
bool isDelcaredScopeVariable(Scope* scope, Literal key);
|
bool isDelcaredScopeVariable(Scope* scope, Literal key);
|
||||||
|
|
||||||
//return false if undefined
|
//return false if undefined
|
||||||
bool setScopeVariable(Scope* scope, Literal key, Literal value);
|
bool setScopeVariable(Scope* scope, Literal key, Literal value, bool constCheck);
|
||||||
bool getScopeVariable(Scope* scope, Literal key, Literal* value);
|
bool getScopeVariable(Scope* scope, Literal key, Literal* value);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user