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

Commit

Permalink
typecheck lambda expr
Browse files Browse the repository at this point in the history
  • Loading branch information
SaptakBhoumik committed Aug 6, 2022
1 parent 39aa693 commit d1c282a
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 29 deletions.
14 changes: 13 additions & 1 deletion Peregrine/analyzer/ast_validate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -916,7 +916,19 @@ bool Validator::visit(const TernaryFor& node){

bool Validator::visit(const LambdaDefinition& node){
node.body()->accept(*this);
validate_parameters(node.parameters());
auto param=node.parameters();
for(auto& x:param){
if(x.p_default->type()!=KAstNoLiteral){
add_error(x.p_name->token(), "SyntaxError: Lambda parameters cannot have default values");
}
if(x.p_paramType!=Normal){
add_error(x.p_name->token(), "SyntaxError: Lambda parameters cannot have ellipses,kwargs or varargs");
}
if(x.p_type->type()==KAstNoLiteral){
add_error(x.p_name->token(), "SyntaxError: Must specify the type of a lambda parameter");
}
}
validate_parameters(param);
return true;
}

Expand Down
22 changes: 22 additions & 0 deletions Peregrine/analyzer/typeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -782,4 +782,26 @@ bool TypeChecker::visit(const ast::MultipleAssign& node){
nonConstNode.set_assign_type(assign_type);
return true;
}
bool TypeChecker::visit(const ast::LambdaDefinition& node){
auto params=node.parameters();
auto body=node.body();
std::vector<TypePtr> param_type;
EnvPtr oldEnv = m_env;
m_env = createEnv(oldEnv);
for(auto& param : params){
param.p_type->accept(*this);
param_type.push_back(m_result);
m_env->set(identifierName(param.p_name), m_result);
}
body->accept(*this);
auto return_type=m_result;
if (return_type!=NULL){
auto& nonconstnode = const_cast<ast::LambdaDefinition&>(node);
nonconstnode.set_return_type(return_type->getTypeAst());
}
m_env=oldEnv;
auto functionType =std::make_shared<FunctionType>(param_type, return_type);
m_result=functionType;
return true;
}
}
2 changes: 1 addition & 1 deletion Peregrine/analyzer/typeChecker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ class TypeChecker : public ast::AstVisitor {
bool visit(const ast::ForStatement& node);
bool visit(const ast::MatchStatement& node);
bool visit(const ast::ScopeStatement& node);
// bool visit(const ast::CppStatement& node);
bool visit(const ast::ReturnStatement& node);
bool visit(const ast::DecoratorStatement& node);
bool visit(const ast::ListLiteral& node);
Expand Down Expand Up @@ -79,6 +78,7 @@ class TypeChecker : public ast::AstVisitor {
bool visit(const ast::MultipleAssign& node);
bool visit(const ast::ExpressionTuple& node);
bool visit(const ast::TypeTuple& node);
bool visit(const ast::LambdaDefinition& node);

std::string m_filename;
TypePtr m_result;
Expand Down
41 changes: 15 additions & 26 deletions Peregrine/ast/ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1847,6 +1847,12 @@ Token LambdaDefinition::token() const{
AstKind LambdaDefinition::type() const{
return KAstLambda;
}
void LambdaDefinition::set_return_type(AstNodePtr return_type){
m_returnType=return_type;
}
AstNodePtr LambdaDefinition::return_type() const{
return m_returnType;
}
std::string LambdaDefinition::stringify() const{
std::string res="def(";
if (!m_parameters.empty()) {
Expand All @@ -1859,34 +1865,17 @@ std::string LambdaDefinition::stringify() const{
if(param.is_const){
res += "const ";
}
if(param.p_paramType==VarKwarg){
res += param.p_type->stringify();
res += param.p_name->stringify();
}
else if(param.p_paramType==VarArg){
res += param.p_type->stringify();
res += param.p_name->stringify();
}
else if(param.p_paramType==Ellipses){
res += param.p_type->stringify();
if(param.p_name->type()!=KAstNoLiteral){
res += param.p_name->stringify();
}
}
else{
res += param.p_name->stringify();
if (param.p_type->type()!=KAstNoLiteral){
res += ":";
res += param.p_type->stringify();
}
if (param.p_default->type()!=ast::KAstNoLiteral){
res+="=";
res+=param.p_default->stringify();
}
}

res += param.p_name->stringify();
res += ":";
res += param.p_type->stringify();
}
}
res+="):"+m_body->stringify();
res+=")";
if(m_returnType!=nullptr){
res+="->"+m_returnType->stringify();
}
res+=":"+m_body->stringify();
return res;
}
GenericCall::GenericCall(Token tok,std::vector<AstNodePtr> generic_types,AstNodePtr identifier){
Expand Down
3 changes: 3 additions & 0 deletions Peregrine/ast/ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1291,12 +1291,15 @@ class LambdaDefinition : public AstNode {
Token m_tok;
std::vector<parameter> m_parameters;
AstNodePtr m_body;
AstNodePtr m_returnType=nullptr;

public:
LambdaDefinition(Token tok,std::vector<parameter> parameters, AstNodePtr body);

std::vector<parameter> parameters() const;
void set_return_type(AstNodePtr return_type);
AstNodePtr body() const;
AstNodePtr return_type() const;
Token token() const;
AstKind type() const;
std::string stringify() const;
Expand Down
5 changes: 4 additions & 1 deletion Peregrine/parser/expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,13 +386,16 @@ AstNodePtr Parser::parseCast() {
}
AstNodePtr Parser::parseLambda(){
//parses lambda expression
//def (arg1,arg2:type):value_to_return
//def (arg2:type):value_to_return
auto tok=m_currentToken;
expect(tk_l_paren,"Expected a ( but got "+next().keyword+" instead");
std::vector<parameter> parameters;

advance();
while (m_currentToken.tkType != tk_r_paren) {
//parseParameter() function also parses the default parameter and allows args without type which is not
//allowed in lambda expressions.We will parse the parameters as normal and then check if they are valid
//or else we will throw an error.This is done in the ast validator.
parameters.push_back(parseParameter());
if (m_currentToken.tkType == tk_comma) {
advance();
Expand Down
3 changes: 3 additions & 0 deletions Peregrine/test.pe
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,8 @@ def may():
c1:union_test1
c.b.a=4
return c.b.a,test.a,c
def june(a:int)->int:
return a
def main():
j=def (x:int):june(x)
a,b,u=may()

0 comments on commit d1c282a

Please sign in to comment.