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 9, 2022
1 parent d1c282a commit c682672
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 6 deletions.
91 changes: 91 additions & 0 deletions Peregrine/analyzer/typeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,59 @@ bool TypeChecker::visit(const ast::FunctionDefinition& node) {
return true;
}

bool TypeChecker::visit(const ast::MethodDefinition& node) {
EnvPtr oldEnv = m_env;
m_env = createEnv(oldEnv);

std::vector<TypePtr> parameterTypes;
parameterTypes.reserve(node.parameters().size()+1);
auto reciever = node.reciever();
if(reciever.p_type->type()!=ast::KAstNoLiteral){
reciever.p_type->accept(*this);
parameterTypes.push_back(m_result);
m_env->set(identifierName(reciever.p_name), m_result);
}
for (auto& param : node.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);
}
node.returnType()->accept(*this);
auto returnType=m_result;
auto methodType =
std::make_shared<FunctionType>(parameterTypes, returnType,true);

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

m_env = oldEnv;

m_env->set(identifierName(node.name()), methodType);
return true;
}

bool TypeChecker::visit(const ast::VariableStatement& node) {
//TODO:check if redefination
auto& nonConstNode = const_cast<ast::VariableStatement&>(node);
Expand All @@ -161,6 +214,13 @@ bool TypeChecker::visit(const ast::VariableStatement& node) {
add_error(node.token(), "You cant declare a variable of type void");
return true;
}
else if(m_result->category()==Function){
auto cast=std::dynamic_pointer_cast<FunctionType>(m_result);
if(cast->isMethod()){
add_error(node.token(), "You cant declare a variable of type `method`");
return true;
}
}
nonConstNode.setProcessedType(m_result,defined_before);
varType = m_result;
} else{
Expand Down Expand Up @@ -204,6 +264,13 @@ bool TypeChecker::visit(const ast::ConstDeclaration& node) {
add_error(node.token(), "You cant declare a constant of type void");
return true;
}
else if(m_result->category()==Function){
auto cast=std::dynamic_pointer_cast<FunctionType>(m_result);
if(cast->isMethod()){
add_error(node.token(), "You cant declare a variable of type `method`");
return true;
}
}
nonConstNode.setProcessedType(m_result);
constType = m_result;
} else{
Expand Down Expand Up @@ -804,4 +871,28 @@ bool TypeChecker::visit(const ast::LambdaDefinition& node){
m_result=functionType;
return true;
}
bool TypeChecker::visit(const ast::ExternStatement& node){
//TODO:prevent extern name with same variabel
extern_libs[node.name()]=node.libs();
return true;
}
bool TypeChecker::visit(const ast::ExternFuncDef& node) {
//TODO:complete it
if(!extern_libs.contains(node.owner())){
add_error(node.token(), "Library "+node.owner()+" not found");
return true;
}
auto name = node.name();
auto params = node.parameters();
std::vector<TypePtr> param_type;
for (auto& param : params) {
param->accept(*this);
param_type.push_back(m_result);
}
node.returnType()->accept(*this);
auto return_type = m_result;
auto functionType = std::make_shared<FunctionType>(param_type, return_type);
// m_env->extern_set(name, functionType);
return true;
}
}
4 changes: 4 additions & 0 deletions Peregrine/analyzer/typeChecker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class TypeChecker : public ast::AstVisitor {
bool visit(const ast::ClassDefinition& node);
bool visit(const ast::ImportStatement& node);
bool visit(const ast::FunctionDefinition& node);
bool visit(const ast::MethodDefinition& node);
bool visit(const ast::VariableStatement& node);
bool visit(const ast::ConstDeclaration& node);
bool visit(const ast::TypeDefinition& node);
Expand Down Expand Up @@ -79,6 +80,8 @@ class TypeChecker : public ast::AstVisitor {
bool visit(const ast::ExpressionTuple& node);
bool visit(const ast::TypeTuple& node);
bool visit(const ast::LambdaDefinition& node);
bool visit(const ast::ExternStatement& node);
bool visit(const ast::ExternFuncDef& node);

std::string m_filename;
TypePtr m_result;
Expand All @@ -87,6 +90,7 @@ class TypeChecker : public ast::AstVisitor {
// the function whose body is being currently checked
std::shared_ptr<FunctionType> m_currentFunction;
TypePtr m_returnType=NULL;//current return type
std::map<std::string,std::vector<std::string>> extern_libs;//the c libs that are imported
};
}
#endif
4 changes: 4 additions & 0 deletions Peregrine/ast/ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1585,6 +1585,10 @@ Token MethodDefinition::token() const { return m_token; }

AstKind MethodDefinition::type() const { return KAstMethodDef; }

void MethodDefinition::setType(types::TypePtr type){
m_returnType=type->getTypeAst();
}

std::string MethodDefinition::stringify() const {
std::string res = "def (";
if(m_reciever.is_const){
Expand Down
1 change: 1 addition & 0 deletions Peregrine/ast/ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1166,6 +1166,7 @@ class MethodDefinition : public AstNode {
AstKind type() const;
std::string stringify() const;
void accept(AstVisitor& visitor) const;
void setType(types::TypePtr type);
};
class ExternFuncDef : public AstNode {
Token m_token;
Expand Down
11 changes: 9 additions & 2 deletions Peregrine/ast/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -581,12 +581,19 @@ ast::AstNodePtr UserDefinedType::getTypeAst() const {
}

FunctionType::FunctionType(std::vector<TypePtr> parameterTypes,
TypePtr returnType) {
TypePtr returnType,bool is_user_defined_method) {
m_parameterTypes = parameterTypes;
m_returnType = returnType;
m_is_user_defined_method=is_user_defined_method;
}

TypeCategory FunctionType::category() const { return TypeCategory::Function; }
TypeCategory FunctionType::category() const {
return TypeCategory::Function;
}

bool FunctionType::isMethod() const{
return m_is_user_defined_method;
}

const std::vector<TypePtr>& FunctionType::parameterTypes() const {
return m_parameterTypes;
Expand Down
4 changes: 3 additions & 1 deletion Peregrine/ast/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,14 +228,16 @@ class UserDefinedType : public Type {
};

class FunctionType : public Type {
bool m_is_user_defined_method=false;
std::vector<TypePtr> m_parameterTypes;
TypePtr m_returnType;

public:
FunctionType(std::vector<TypePtr> parameterTypes, TypePtr returnType);
FunctionType(std::vector<TypePtr> parameterTypes, TypePtr returnType,bool is_user_defined_method=false);

ast::AstNodePtr getTypeAst() const;
TypeCategory category() const;
bool isMethod() const;
const std::vector<TypePtr>& parameterTypes() const;
TypePtr returnType() const;
bool isConvertibleTo(const Type& type) const;
Expand Down
4 changes: 2 additions & 2 deletions Peregrine/parser/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,8 +458,8 @@ AstNodePtr Parser::parseExtern(){
auto name=m_currentToken.keyword;
std::vector<std::string> libs;
expect(tk_assign,"Expected = but got "+next().keyword+" instead","","","");
expect(tk_import,"Expected = but got "+next().keyword+" instead","","","");
expect(tk_l_paren,"Expected = but got "+next().keyword+" instead","","","");
expect(tk_import,"Expected `import` but got "+next().keyword+" instead","","","");
expect(tk_l_paren,"Expected `(` but got "+next().keyword+" instead","","","");
while(m_currentToken.tkType!=tk_r_paren){
expect(tk_string,"Expected string but got "+next().keyword+" instead","","","");
libs.push_back(m_currentToken.keyword);
Expand Down
7 changes: 6 additions & 1 deletion Peregrine/test.pe
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ def may():
return c.b.a,test.a,c
def june(a:int)->int:
return a
def (x:int)f():
return x
extern x=import("c")
def main():
m=may
#l=f Should be an error
j=def (x:int):june(x)
a,b,u=may()
a,b,c=m()

0 comments on commit c682672

Please sign in to comment.