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

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
SaptakBhoumik committed Aug 19, 2022
1 parent c682672 commit c424195
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 7 deletions.
16 changes: 15 additions & 1 deletion Peregrine/analyzer/ast_validate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,21 @@ bool Validator::visit(const ReturnStatement& node){
bool Validator::visit(const ContinueStatement& node){return true;}
bool Validator::visit(const BreakStatement& node){return true;}
bool Validator::visit(const DecoratorStatement& node){
node.body()->accept(*this);
switch (node.body()->type()){
case KAstMethodDef:{
add_error(node.body()->token(),"Error: Method that is modifying a type can't be decorated",
"Define a regular function instead");
break;
}
case KAstExternFuncDef:{
add_error(node.body()->token(),"Error: Defination of external function can't be decorated from peregrine",
"Use the library directly in that language");
break;
}
default:{
node.body()->accept(*this);
}
}
auto x=node.decoratorItem();
for (auto& y:x){
y->accept(*this);
Expand Down
108 changes: 105 additions & 3 deletions Peregrine/analyzer/typeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,22 @@ void TypeChecker::check(ast::AstNodePtr expr, const TypePtr expTypePtr) {
}
}

void TypeChecker::check(const TypePtr exprType, const TypePtr expTypePtr,Token tok) {
if(expTypePtr==NULL||exprType==NULL){
return;
}
if (*exprType != *expTypePtr) {
if (!exprType->isConvertibleTo(*expTypePtr) &&
!expTypePtr->isConvertibleTo(*exprType)) {
add_error(tok, "expected type " + expTypePtr->stringify() +
", got " + exprType->getTypeAst()->stringify() +
" instead");
}

// TODO: convert one type to another
}
}

std::string TypeChecker::identifierName(ast::AstNodePtr identifier) {
assert(identifier->type() == ast::KAstIdentifier);

Expand Down Expand Up @@ -206,7 +222,10 @@ bool TypeChecker::visit(const ast::VariableStatement& node) {
if (varType->category() == TypeCategory::Void) {
// inferring the type of the variable
node.value()->accept(*this);
if(m_result->category()==MultipleReturn){
if(m_result==NULL){
return true;
}
else if(m_result->category()==MultipleReturn){
add_error(node.token(), "Too few variables on the left hand side");
return true;
}
Expand Down Expand Up @@ -397,7 +416,90 @@ bool TypeChecker::visit(const ast::ReturnStatement& node) {
return true;
}

bool TypeChecker::visit(const ast::DecoratorStatement& node) { return true; }
bool TypeChecker::visit(const ast::DecoratorStatement& node) {
auto function=std::dynamic_pointer_cast<ast::FunctionDefinition>(node.body());
{
EnvPtr oldEnv = m_env;
m_env = createEnv(oldEnv);

std::vector<TypePtr> parameterTypes;
parameterTypes.reserve(function->parameters().size());

for (auto& param : function->parameters()) {
if (param.p_default->type() != ast::KAstNoLiteral) {
if (param.p_type->type() != ast::KAstNoLiteral) {
param.p_type->accept(*this);
check(param.p_default, m_result);
}

param.p_default->accept(*this);
parameterTypes.push_back(m_result);
m_env->set(identifierName(param.p_name), m_result);
continue;
}

param.p_type->accept(*this);
parameterTypes.push_back(m_result);
m_env->set(identifierName(param.p_name), m_result);
}
function->returnType()->accept(*this);
auto returnType=m_result;
auto functionType =
std::make_shared<FunctionType>(parameterTypes, returnType);

auto oldFunction = m_currentFunction;
auto oldReturnType = m_returnType;
m_returnType = NULL;
m_currentFunction = functionType;
function->body()->accept(*this);
if(m_returnType!=NULL){
auto& nonconstnode = const_cast<ast::FunctionDefinition&>(*function);
nonconstnode.setType(m_returnType);
functionType =std::make_shared<FunctionType>(parameterTypes, m_returnType);
}
m_returnType = oldReturnType;
m_currentFunction = oldFunction;

m_env = oldEnv;
m_result = functionType;
}
auto function_type=m_result;
std::vector<TypePtr> args;
auto decorators=node.decoratorItem();
for(size_t i=0;i<decorators.size();i++){
args.clear();
args.push_back(m_result);
auto decorator=decorators[decorators.size()-i-1];
//TODO: Dot expression and arrow expression
if(decorator->type()==ast::KAstFunctionCall){
auto call=std::dynamic_pointer_cast<ast::FunctionCall>(decorator);
for(auto& arg:call->arguments()){
arg->accept(*this);
args.push_back(m_result);
}
decorator=call->name();
}
decorator->accept(*this);
if (m_result->category() != TypeCategory::Function){
add_error(node.token(), identifierName(decorator) + " is not a function");
return true;
}
auto decoratorType = std::dynamic_pointer_cast<FunctionType>(m_result);
if (decoratorType->parameterTypes().size() != args.size()){
add_error(node.token(), "invalid number of arguments passed to " +
identifierName(decorator));
return true;
}
for (size_t i = 0; i < args.size(); i++) {
auto paramType = decoratorType->parameterTypes()[i];
auto argType = args[i];
check(argType, paramType);
}
m_result = decoratorType->returnType();
}
m_env->set(identifierName(function->name()), m_result);
return true;
}

bool TypeChecker::visit(const ast::ListLiteral& node) {
//TODO: If the variable is empty do something for the variable
Expand Down Expand Up @@ -872,7 +974,7 @@ bool TypeChecker::visit(const ast::LambdaDefinition& node){
return true;
}
bool TypeChecker::visit(const ast::ExternStatement& node){
//TODO:prevent extern name with same variabel
//TODO:prevent extern name with same variable
extern_libs[node.name()]=node.libs();
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 @@ -27,7 +27,8 @@ class TypeChecker : public ast::AstVisitor {
void checkBody(ast::AstNodePtr body,
std::vector<std::pair<TypePtr,ast::AstNodePtr>> add_var={});

void check(ast::AstNodePtr expr, const TypePtr expectedType);
void check(ast::AstNodePtr expr, const TypePtr expTypePtr);
void check(const TypePtr exprType, const TypePtr expTypePtr, Token tok={});

bool visit(const ast::ClassDefinition& node);
bool visit(const ast::ImportStatement& node);
Expand Down
13 changes: 11 additions & 2 deletions Peregrine/test.pe
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,17 @@ def june(a:int)->int:
def (x:int)f():
return x
extern x=import("c")
def testing(f:def(int)->int):
return f(4)
def testing1(x:int,h:int):
return x*h
@testing1(0)
@testing
def testing2(x:int):
return x*x
def main():
m=may
#l=f Should be an error
#l=f #Should be an error
j=def (x:int):june(x)
a,b,c=m()
a,b,c=m()
n=testing2

0 comments on commit c424195

Please sign in to comment.