-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
335 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#include "ASTRuntime.h" | ||
|
||
#include "AnalysisFreeVars.h" | ||
|
||
#include <utility> | ||
|
||
using namespace ast; | ||
|
||
Closure::Closure(const Lambda &Lbd, const std::vector<Environment> &Envs) | ||
: ClonableNode(ASTNodeKind::AST_Closure), | ||
L(std::unique_ptr<Lambda>(static_cast<Lambda *>(Lbd.clone()))) { | ||
|
||
// To create a closure we need to: | ||
|
||
// 1. Find the free variables in the lambda. | ||
AnalysisFreeVars AFV; | ||
L->accept(AFV); | ||
auto const &FreeVars = AFV.getResult(); | ||
|
||
// 2. Find in the current environment, the values of the free variables | ||
// and save them. | ||
for (auto const &Var : FreeVars) { | ||
for (auto const &E : llvm::reverse(Envs)) { | ||
auto const &Val = E.lookup(Var); | ||
if (Val) { | ||
Env.add(Var, std::unique_ptr<ValueNode>(Val->clone())); | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
Closure::Closure(const Closure &Other) | ||
: ClonableNode(ASTNodeKind::AST_Closure), | ||
L(std::unique_ptr<Lambda>(static_cast<Lambda *>(Other.L->clone()))) { | ||
for (auto const &E : Other.Env) { | ||
Env.add(E.first, std::unique_ptr<ValueNode>(E.second->clone())); | ||
} | ||
} | ||
|
||
void Closure::dump() const {} | ||
void Closure::write() const {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
#include "AnalysisFreeVars.h" | ||
|
||
void AnalysisFreeVars::visit(ast::Identifier const &Id) { | ||
// If the identifier is not in the environment, then it is a free variable. | ||
|
||
for (auto const &Var : llvm::reverse(Vars)) { | ||
if (Var.count(Id) == 0) { | ||
Result.insert(Id); | ||
} | ||
} | ||
} | ||
|
||
void AnalysisFreeVars::visit(ast::Integer const &Int) { | ||
// Integers do not have free variables. | ||
// Nothing to do. | ||
} | ||
|
||
void AnalysisFreeVars::visit(ast::Linklet const &Linklet) { | ||
llvm::errs() << "Free variable analysis only applies to expressions.\n"; | ||
} | ||
|
||
void AnalysisFreeVars::visit(ast::DefineValues const &DV) { | ||
llvm::errs() << "Free variable analysis only applies to expressions.\n"; | ||
} | ||
|
||
void AnalysisFreeVars::visit(ast::Values const &V) { | ||
// Need to check for free variable in each expression of the Values | ||
// expression. | ||
for (auto const &Expr : V.getExprs()) { | ||
Expr->accept(*this); | ||
} | ||
} | ||
|
||
void AnalysisFreeVars::visit(ast::Void const &Vd) { | ||
// Void expressions have no free variables. | ||
// Nothing to do. | ||
} | ||
|
||
void AnalysisFreeVars::visit(ast::Lambda const &L) { | ||
const ast::Formal &F = L.getFormals(); | ||
std::set<ast::Identifier> FormalVars; | ||
|
||
if (F.getType() == ast::Formal::Type::Identifier) { | ||
auto IF = static_cast<const ast::IdentifierFormal &>(F); | ||
FormalVars.insert(IF.getIdentifier()); | ||
} else if (F.getType() == ast::Formal::Type::List) { | ||
auto LF = static_cast<const ast::ListFormal &>(F); | ||
for (auto const &Id : LF.getIds()) { | ||
FormalVars.insert(Id); | ||
} | ||
} else if (F.getType() == ast::Formal::Type::ListRest) { | ||
auto LRF = static_cast<const ast::ListRestFormal &>(F); | ||
for (auto const &Id : LRF.getIds()) { | ||
FormalVars.insert(Id); | ||
} | ||
FormalVars.insert(LRF.getRestFormal()); | ||
} | ||
|
||
// Save the current environment. | ||
Vars.push_back(FormalVars); | ||
|
||
// Check for free variables in the body of the lambda. | ||
L.getBody().accept(*this); | ||
|
||
// Restore the environment. | ||
Vars.pop_back(); | ||
} | ||
|
||
void AnalysisFreeVars::visit(ast::Closure const &L) { | ||
// Closures by definition do not have free variables. | ||
// Nothing to do. | ||
} | ||
|
||
void AnalysisFreeVars::visit(ast::Begin const &B) { | ||
// Iterate through all the begin expressions and check for free variables. | ||
for (auto const &Expr : B.getBody()) { | ||
Expr->accept(*this); | ||
} | ||
} | ||
|
||
void AnalysisFreeVars::visit(ast::List const &L) { | ||
// Iterate through all the List expressions and check for free variables. | ||
for (auto const &Expr : L.values()) { | ||
Expr->accept(*this); | ||
} | ||
} | ||
|
||
void AnalysisFreeVars::visit(ast::Application const &A) { | ||
// Iterate through all the Application expressions and check for free | ||
// variables. | ||
for (auto const &Expr : A.getExprs()) { | ||
Expr->accept(*this); | ||
} | ||
} | ||
|
||
void AnalysisFreeVars::visit(ast::SetBang const &SB) { | ||
// Check for free variables on the right hand side expression of SetBang | ||
// expression. | ||
SB.getExpr().accept(*this); | ||
} | ||
|
||
void AnalysisFreeVars::visit(ast::IfCond const &If) { | ||
// Check for free variables on the condition expression of IfCond expression. | ||
If.getCond().accept(*this); | ||
// Check for free variables on the consequent expression of IfCond expression. | ||
If.getThen().accept(*this); | ||
// Check for free variables on the alternative expression of IfCond | ||
// expression. | ||
If.getElse().accept(*this); | ||
} | ||
|
||
void AnalysisFreeVars::visit(ast::BooleanLiteral const &Bool) { | ||
// Boolean literals have no free variables. | ||
// Nothing to do. | ||
} | ||
|
||
void AnalysisFreeVars::visit(ast::LetValues const &LV) { | ||
std::set<ast::Identifier> LVVars; | ||
for (size_t Idx = 0; Idx < LV.bindingCount(); Idx++) | ||
for (auto const &Var : LV.getBindingIds(Idx)) | ||
LVVars.insert(Var); | ||
|
||
Vars.push_back(LVVars); | ||
|
||
for (size_t Idx = 0; Idx < LV.bodyCount(); Idx++) | ||
LV.getBodyExpr(Idx).accept(*this); | ||
|
||
Vars.pop_back(); | ||
} | ||
|
||
void AnalysisFreeVars::visit(ast::RuntimeFunction const &LV) { | ||
// Runtime Functions have no free variables. | ||
// Nothing to do. | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#pragma once | ||
|
||
#include "ast.h" | ||
#include "environment.h" | ||
|
||
#include <memory> | ||
|
||
namespace ast { | ||
// | ||
// This file includes the structures that are used in addition to | ||
// those in ast.h during runtime interpretation. | ||
// | ||
// The simplest example is the Closure. | ||
|
||
// A Closure is a runtime manifestation of a Lambda. | ||
class Closure : public ClonableNode<Closure, ValueNode> { | ||
public: | ||
Closure(const Lambda &Lbd, const std::vector<Environment> &Envs); | ||
Closure(const Closure &Other); | ||
|
||
static bool classof(const ASTNode *N) { | ||
return N->getKind() == ASTNodeKind::AST_Closure; | ||
} | ||
|
||
void dump() const override; | ||
void write() const override; | ||
|
||
const Lambda &getLambda() const { return *L; } | ||
const Environment &getEnvironment() const { return Env; } | ||
|
||
private: | ||
std::unique_ptr<Lambda> L; | ||
Environment Env; | ||
}; | ||
|
||
}; // namespace ast |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#pragma once | ||
|
||
#include "ASTVisitor.h" | ||
#include "ast.h" | ||
|
||
#include <llvm/ADT/STLExtras.h> | ||
|
||
#include <cassert> | ||
#include <map> | ||
#include <memory> | ||
#include <set> | ||
#include <vector> | ||
|
||
// File implementing free variable analysis for expressions. | ||
|
||
class AnalysisFreeVars : public ASTVisitor { | ||
public: | ||
virtual void visit(ast::Identifier const &Id) override; | ||
virtual void visit(ast::Integer const &Int) override; | ||
virtual void visit(ast::Linklet const &Linklet) override; | ||
virtual void visit(ast::DefineValues const &DV) override; | ||
virtual void visit(ast::Values const &V) override; | ||
virtual void visit(ast::Void const &Vd) override; | ||
virtual void visit(ast::Lambda const &L) override; | ||
virtual void visit(ast::Closure const &L) override; | ||
virtual void visit(ast::Begin const &B) override; | ||
virtual void visit(ast::List const &L) override; | ||
virtual void visit(ast::Application const &A) override; | ||
virtual void visit(ast::SetBang const &SB) override; | ||
virtual void visit(ast::IfCond const &If) override; | ||
virtual void visit(ast::BooleanLiteral const &Bool) override; | ||
virtual void visit(ast::LetValues const &LV) override; | ||
virtual void visit(ast::RuntimeFunction const &LV) override; | ||
|
||
// Get the current saved result. | ||
std::set<ast::Identifier> getResult() const { return Result; }; | ||
|
||
private: | ||
std::set<ast::Identifier> Result; /// List of free variables. | ||
llvm::SmallVector<std::set<ast::Identifier>> | ||
Vars; /// Environment map for identifiers. | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.