Skip to content
This repository has been archived by the owner on Nov 24, 2024. It is now read-only.

Commit

Permalink
improvement to typechecker
Browse files Browse the repository at this point in the history
  • Loading branch information
SaptakBhoumik committed Jun 9, 2022
1 parent 36f167e commit bd6fdcd
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 13 deletions.
70 changes: 61 additions & 9 deletions Peregrine/analyzer/typeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,15 @@ EnvPtr TypeChecker::createEnv(EnvPtr parent) {
return std::make_shared<SymbolTable<TypePtr>>(parent);
}

void TypeChecker::checkBody(ast::AstNodePtr body) {
void TypeChecker::checkBody(ast::AstNodePtr body,
std::vector<std::pair<TypePtr,ast::AstNodePtr>> add_var) {
EnvPtr previousEnv = m_env;
m_env = createEnv();
if(add_var.size()!=0) {
for(auto& var : add_var) {
m_env->set(var.second,var.first);
}
}
body->accept(*this);
m_env = previousEnv;
}
Expand Down Expand Up @@ -179,8 +185,9 @@ bool TypeChecker::visit(const ast::IfStatement& node) {
checkBody(elif.second);
}

if (node.elseBody()->type() != ast::KAstNoLiteral)
if (node.elseBody()->type() != ast::KAstNoLiteral){
checkBody(node.elseBody());
}
return true;
}

Expand All @@ -191,11 +198,21 @@ bool TypeChecker::visit(const ast::AssertStatement& node) {

bool TypeChecker::visit(const ast::StaticStatement& node) { return true; }

bool TypeChecker::visit(const ast::ExportStatement& node) { return true; }
bool TypeChecker::visit(const ast::ExportStatement& node) {
node.body()->accept(*this);
return true;
}

bool TypeChecker::visit(const ast::InlineStatement& node) { return true; }
bool TypeChecker::visit(const ast::InlineStatement& node) {
node.body()->accept(*this);
return true;
}

bool TypeChecker::visit(const ast::RaiseStatement& node) { return true; }
bool TypeChecker::visit(const ast::RaiseStatement& node) {
//TODO: Check if the exception is a subclass of the exception in the except block
node.value()->accept(*this);
return true;
}

bool TypeChecker::visit(const ast::WhileStatement& node) {
check(node.condition(), *TypeProducer::boolean());
Expand Down Expand Up @@ -312,7 +329,19 @@ bool TypeChecker::visit(const ast::PrefixExpression& node) {
return true;
}

bool TypeChecker::visit(const ast::PostfixExpression& node) { return true; }
bool TypeChecker::visit(const ast::PostfixExpression& node) {
node.left()->accept(*this);
TypePtr result = m_result->postfixOperatorResult(node.postfix());

if (!result) {
add_error(node.token(), "operator " + node.postfix().keyword +
" can not be used with type " +
m_result->stringify());
}

m_result = result;
return true;
}

bool TypeChecker::visit(const ast::FunctionCall& node) {
node.name()->accept(*this);
Expand Down Expand Up @@ -387,7 +416,18 @@ bool TypeChecker::visit(const ast::ListTypeExpr& node) {
return true;
}

bool TypeChecker::visit(const ast::FunctionTypeExpr& node) { return true; }
bool TypeChecker::visit(const ast::FunctionTypeExpr& node) {
std::vector<TypePtr> parameterTypes;
auto args=node.argTypes();
for (auto& param : args) {
param->accept(*this);
parameterTypes.push_back(m_result);
}
node.returnTypes()->accept(*this);
auto returnType = m_result;
m_result = TypeProducer::function(parameterTypes, returnType);
return true;
}

bool TypeChecker::visit(const ast::PointerTypeExpr& node) {
node.baseType()->accept(*this);
Expand Down Expand Up @@ -469,8 +509,20 @@ bool TypeChecker::visit(const ast::TryExcept& node) {
auto except_clauses = node.except_clauses();
for(auto except_clause : except_clauses){
//TODO: Check if the exception is a subclass of the exception in the except block
//TODO:Also add the alias of exception to the environment
checkBody(except_clause.second);
auto exception=except_clause.first.first;
std::vector<std::pair<TypePtr,ast::AstNodePtr>> add_var={};
if(exception.size()>0){
exception[0]->accept(*this);
auto type=m_result;
for(size_t i=1;i<exception.size();i++){
check(exception[i],*type);
}
if(except_clause.first.second->type()!=ast::KAstNoLiteral){
std::pair<TypePtr,ast::AstNodePtr> var=std::make_pair(type,except_clause.first.second);
add_var.push_back(var);
}
}
checkBody(except_clause.second,add_var);
}
return true;
}
Expand Down
3 changes: 2 additions & 1 deletion Peregrine/analyzer/typeChecker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ class TypeChecker : public ast::AstVisitor {
void add_error(Token tok, std::string_view msg);
EnvPtr createEnv(EnvPtr parent = nullptr);
std::string identifierName(ast::AstNodePtr identifier);
void checkBody(ast::AstNodePtr body);
void checkBody(ast::AstNodePtr body,
std::vector<std::pair<TypePtr,ast::AstNodePtr>> add_var={});

void check(ast::AstNodePtr expr, const Type& expectedType);

Expand Down
5 changes: 4 additions & 1 deletion Peregrine/ast/ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ types::TypePtr VariableStatement::processedType() const {

void VariableStatement::setProcessedType(types::TypePtr processedType,bool defined_before) {
m_processedType = processedType;
if(!defined_before){
if(!defined_before&&m_processedType!=NULL){
m_type=m_processedType->getTypeAst();
}
}
Expand Down Expand Up @@ -518,6 +518,9 @@ types::TypePtr ConstDeclaration::processedType() const {

void ConstDeclaration::setProcessedType(types::TypePtr processedType) {
m_processedType = processedType;
if(m_processedType!=NULL){
m_type=m_processedType->getTypeAst();
}
}

Token ConstDeclaration::token() const { return m_token; }
Expand Down
41 changes: 39 additions & 2 deletions Peregrine/ast/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ TypePtr IntType::prefixOperatorResult(Token op) const {
}
}

TypePtr IntType::postfixOperatorResult(Token op) const{
return TypeProducer::integer();
}

TypePtr IntType::infixOperatorResult(Token op, const TypePtr type) const {
switch (type->category()) {
case TypeCategory::Integer:
Expand All @@ -102,7 +106,12 @@ TypePtr IntType::infixOperatorResult(Token op, const TypePtr type) const {
if (TokenUtils::isComparisonToken(op))
return TypeProducer::boolean();

// TODO: handle bitwise operations
if (TokenUtils::isBitwiseToken(op)){
if(type->category()==TypeCategory::Integer)
return type;
else
return nullptr;
}
return nullptr;
}

Expand Down Expand Up @@ -228,6 +237,10 @@ TypePtr DecimalType::prefixOperatorResult(Token op) const {
}
}

TypePtr DecimalType::postfixOperatorResult(Token op) const{
return TypeProducer::decimal();
}

TypePtr DecimalType::infixOperatorResult(Token op, const TypePtr type) const {
switch (type->category()) {
case TypeCategory::Integer:
Expand Down Expand Up @@ -296,6 +309,10 @@ TypePtr StringType::prefixOperatorResult(Token op) const {
return nullptr;
}

TypePtr StringType::postfixOperatorResult(Token op) const{
return nullptr;
}

TypePtr StringType::infixOperatorResult(Token op, const TypePtr type) const {
if (type->category() != TypeCategory::String)
return nullptr;
Expand Down Expand Up @@ -401,9 +418,25 @@ TypePtr PointerType::prefixOperatorResult(Token op) const {
return nullptr;
}
}

TypePtr PointerType::postfixOperatorResult(Token op) const{
return TypeProducer::pointer(m_baseType);
}
// TODO: allow pointer arithmetic as normal binary operations?
TypePtr PointerType::infixOperatorResult(Token op, const TypePtr type) const {
switch (type->category()) {
case TypeCategory::Integer:
break;

default:
return nullptr;
}

if (op.tkType==tk_plus || op.tkType==tk_minus)
return TypeProducer::pointer(m_baseType);

if (TokenUtils::isComparisonToken(op))
return TypeProducer::boolean();

return nullptr;
}

Expand Down Expand Up @@ -632,6 +665,10 @@ TypePtr TypeProducer::list(TypePtr elemType, std::string size) {
return std::make_shared<ListType>(elemType, size);
}

TypePtr TypeProducer::function(std::vector<TypePtr> parameterTypes, TypePtr returnType){
return std::make_shared<FunctionType>(parameterTypes, returnType);
}

TypePtr TypeProducer::pointer(TypePtr baseType) {
return std::make_shared<PointerType>(baseType);
}
Expand Down
9 changes: 9 additions & 0 deletions Peregrine/ast/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ class Type {
// e.g. -34 -> Integer
virtual TypePtr prefixOperatorResult(Token op) const { return nullptr; }

// returns the type obtained after applying the given operator to this type
// e.g. 34++ -> Integer
virtual TypePtr postfixOperatorResult(Token op) const { return nullptr; }

// returns the type obtained after applying the given operator to both types
// e.g. false == false -> Bool
virtual TypePtr infixOperatorResult(Token op, const TypePtr type) const {
Expand Down Expand Up @@ -85,6 +89,7 @@ class IntType : public Type {
std::string stringify() const;

TypePtr prefixOperatorResult(Token op) const;
TypePtr postfixOperatorResult(Token op) const;
TypePtr infixOperatorResult(Token op, const TypePtr type) const;

bool operator==(const Type& type) const;
Expand All @@ -110,6 +115,7 @@ class DecimalType : public Type {
bool isFloat() const;

TypePtr prefixOperatorResult(Token op) const;
TypePtr postfixOperatorResult(Token op) const;
TypePtr infixOperatorResult(Token op, const TypePtr type) const;

bool operator==(const Type& type) const;
Expand All @@ -129,6 +135,7 @@ class StringType : public Type {
std::string stringify() const;

TypePtr prefixOperatorResult(Token op) const;
TypePtr postfixOperatorResult(Token op) const;
TypePtr infixOperatorResult(Token op, const TypePtr type) const;
};

Expand Down Expand Up @@ -157,6 +164,7 @@ class PointerType : public Type {
std::string stringify() const;

TypePtr prefixOperatorResult(Token op) const;
TypePtr postfixOperatorResult(Token op) const;
TypePtr infixOperatorResult(Token op, const TypePtr type) const;
};

Expand Down Expand Up @@ -239,6 +247,7 @@ class TypeProducer {
DecimalType::DecimalSize decimalSize = DecimalType::DecimalSize::Float64);
static TypePtr string();
static TypePtr boolean();
static TypePtr function(std::vector<TypePtr> parameterTypes, TypePtr returnType);
static TypePtr voidT();

static TypePtr list(TypePtr elemType, std::string size);
Expand Down
7 changes: 7 additions & 0 deletions Peregrine/utils/symbolTable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "ast/ast.hpp"

#include <iostream>
#include <assert.h>
#include <map>
#include <memory>
#include <algorithm>
Expand Down Expand Up @@ -42,6 +43,12 @@ class SymbolTable {
return true;
}

bool set(ast::AstNodePtr name, T value) {
assert(name->type() == ast::KAstIdentifier);
auto identifier=std::dynamic_pointer_cast<ast::IdentifierExpression>(name);
return set(identifier->value(), value);
}

bool reassign(std::string name, T value) {
if (m_symbols.find(name) == m_symbols.end()) {
if (!m_parent) {
Expand Down

0 comments on commit bd6fdcd

Please sign in to comment.