Type checking in place

This commit is contained in:
2022-08-15 03:52:44 +01:00
parent 8d12db7dbe
commit 6b834ca6d1
4 changed files with 76 additions and 9 deletions

View File

@@ -1 +1,4 @@
;

View File

@@ -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");

View File

@@ -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;
} }

View File

@@ -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);