Skip to content
This repository was archived by the owner on Dec 8, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
98d5c68
Add Python wrapper for JIT
inumanag Sep 26, 2019
a6a9824
Merge remote-tracking branch 'origin/master' into jupyter
Nov 7, 2019
5bb02d7
Add Python wrapper for JIT
inumanag Sep 26, 2019
1fc405b
Add minimal jupyter kernel
Nov 18, 2019
f8e9f2a
Add url for redirect source
Nov 18, 2019
9b570a8
Add syntax highlighting
Nov 22, 2019
37add49
Add kernel inspect hook
Nov 23, 2019
147cb9e
Merge branch 'jupyter' of github.com:seq-lang/seq into jupyter
Nov 29, 2019
e545756
Merge branch 'develop' into jupyter
Nov 29, 2019
f8590cd
Fix pyrpoject.toml dependencies; Fix macOS support
Nov 29, 2019
23b203b
Initial support for JIT autocompletion and introspection
Nov 29, 2019
145bc35
Initial support for JIT autocompletion and introspection
Dec 1, 2019
72c0516
Fix .gitignore
inumanag Dec 1, 2019
a6e5770
Fix JIT issues; Add complete/introspect/doc hooks
inumanag Dec 2, 2019
c7efb91
Merge remote-tracking branch 'origin/develop' into jupyter
inumanag Dec 2, 2019
7030a27
Full support for JIT autocompletion and introspection
Dec 2, 2019
8e5c475
Switch to setuptools
Dec 3, 2019
db9e5ed
Add Jupyter completion and inspection
Dec 4, 2019
ed0eea7
Add pygments lexer to setup
Dec 4, 2019
81aad2c
Small changes
Dec 4, 2019
962b3b3
Add IGV support
inumanag Dec 5, 2019
daa3057
Add IGV support
inumanag Dec 5, 2019
0e0e999
Add jupyter.seq
inumanag Dec 5, 2019
2686ff6
os.path addition; Fix parameters in stdlib; Fix f-string error reporting
inumanag Dec 21, 2019
76913c5
os.path addition
inumanag Dec 21, 2019
a1f0268
Trim whitespace
arshajii Dec 22, 2019
114be88
Remove unused htslib option
arshajii Dec 22, 2019
3632caa
Fix itertools
arshajii Dec 22, 2019
a3aa5ec
Add yield expression
arshajii Dec 23, 2019
0161cd5
Fix revcomp'd sequence matching
arshajii Dec 24, 2019
cc31f8e
Faster k-mer matching
arshajii Dec 24, 2019
1d3259a
Add builtin tags
arshajii Dec 29, 2019
6d7e7b1
Fix ConstructExpr cloning
arshajii Dec 29, 2019
83a2615
Merge branch 'develop' into jupyter
Dec 29, 2019
b70db88
Add partial language server for vscode
Jan 1, 2020
45d9a8c
Add RTLD flags
Jan 6, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,5 @@ dox
# Testing playground #
######################
scratch.seq

.venv
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ install:
# install htslib:
- wget -c https://github.com/samtools/htslib/releases/download/1.9/htslib-1.9.tar.bz2 -O - | tar -xj
- cd htslib-1.9
- ./configure CFLAGS="-fPIC" --disable-libcurl --without-curses
- ./configure CFLAGS="-fPIC" --disable-libcurl
- make
- sudo make install
- cd -
Expand Down
13 changes: 13 additions & 0 deletions compiler/include/seq/expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ class MatchExpr : public Expr {
class ConstructExpr : public Expr {
private:
mutable types::Type *type;
mutable types::Type *type0; // type before deduction, saved for clone
std::vector<Expr *> args;

public:
Expand Down Expand Up @@ -578,6 +579,18 @@ class OptExpr : public Expr {
OptExpr *clone(Generic *ref) override;
};

class YieldExpr : public Expr {
private:
Func *base;

public:
YieldExpr(Func *base);
void resolveTypes() override;
llvm::Value *codegen0(BaseFunc *base, llvm::BasicBlock *&block) override;
types::Type *getType0() const override;
YieldExpr *clone(Generic *ref) override;
};

class DefaultExpr : public Expr {
public:
explicit DefaultExpr(types::Type *type);
Expand Down
1 change: 1 addition & 0 deletions compiler/include/seq/func.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ class Func : public BaseFunc, public Generic, public SrcObject {
void codegenYield(llvm::Value *val, types::Type *type,
llvm::BasicBlock *&block, bool empty = false,
bool dryrun = false);
llvm::Value *codegenYieldExpr(llvm::BasicBlock *&block);

bool isGen() override;
Var *getArgVar(std::string name);
Expand Down
4 changes: 3 additions & 1 deletion compiler/include/seq/funct.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ class GenType : public Type {
llvm::Value *done(llvm::Value *self, llvm::BasicBlock *block);
void resume(llvm::Value *self, llvm::BasicBlock *block,
llvm::BasicBlock *normal, llvm::BasicBlock *unwind);
llvm::Value *promise(llvm::Value *self, llvm::BasicBlock *block);
llvm::Value *promise(llvm::Value *self, llvm::BasicBlock *block,
bool returnPtr = false);
void send(llvm::Value *self, llvm::Value *val, llvm::BasicBlock *block);
void destroy(llvm::Value *self, llvm::BasicBlock *block);
bool fromPrefetch();

Expand Down
4 changes: 4 additions & 0 deletions compiler/include/seq/num.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ class ByteType : public Type {
llvm::Type *getLLVMType(llvm::LLVMContext &context) const override;
size_t size(llvm::Module *module) const override;
static ByteType *get() noexcept;
/// returns ASCII complement table
static llvm::GlobalVariable *
getByteCompTable(llvm::Module *module,
const std::string &name = "seq.byte_comp_table");
};

} // namespace types
Expand Down
29 changes: 26 additions & 3 deletions compiler/lang/expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1943,7 +1943,7 @@ MatchExpr *MatchExpr::clone(Generic *ref) {
}

ConstructExpr::ConstructExpr(types::Type *type, std::vector<Expr *> args)
: Expr(), type(type), args(std::move(args)) {}
: Expr(), type(type), type0(nullptr), args(std::move(args)) {}

types::Type *ConstructExpr::getConstructType() { return type; }

Expand Down Expand Up @@ -2035,8 +2035,10 @@ types::Type *ConstructExpr::getType0() const {

// type parameter deduction if constructing generic class:
auto *ref = dynamic_cast<types::RefType *>(type);
if (ref && ref->numGenerics() > 0 && !ref->realized())
if (ref && ref->numGenerics() > 0 && !ref->realized()) {
type0 = type;
type = ref->realize(ref->deduceTypesFromArgTypes(types));
}

types::Type *ret = type->magicOut("__init__", types);
return ret->is(types::Void) ? type : ret;
Expand All @@ -2046,7 +2048,8 @@ ConstructExpr *ConstructExpr::clone(Generic *ref) {
std::vector<Expr *> argsCloned;
for (auto *arg : args)
argsCloned.push_back(arg->clone(ref));
SEQ_RETURN_CLONE(new ConstructExpr(type->clone(ref), argsCloned));
SEQ_RETURN_CLONE(
new ConstructExpr((type0 ? type0 : type)->clone(ref), argsCloned));
}

MethodExpr::MethodExpr(Expr *self, Func *func)
Expand Down Expand Up @@ -2089,6 +2092,26 @@ OptExpr *OptExpr::clone(Generic *ref) {
SEQ_RETURN_CLONE(new OptExpr(val->clone(ref)));
}

YieldExpr::YieldExpr(Func *base) : Expr(), base(base) {}

void YieldExpr::resolveTypes() { base->resolveTypes(); }

Value *YieldExpr::codegen0(BaseFunc *base, BasicBlock *&block) {
assert(dynamic_cast<Func *>(base) == this->base);
return this->base->codegenYieldExpr(block);
}

types::Type *YieldExpr::getType0() const {
types::GenType *gen = base->getFuncType()->getBaseType(0)->asGen();
if (!gen)
throw exc::SeqException("yield expression in non-generator");
return gen->getBaseType(0);
}

YieldExpr *YieldExpr::clone(Generic *ref) {
SEQ_RETURN_CLONE(new YieldExpr(base->clone(ref)));
}

DefaultExpr::DefaultExpr(types::Type *type) : Expr(type) {}

Value *DefaultExpr::codegen0(BaseFunc *base, BasicBlock *&block) {
Expand Down
21 changes: 21 additions & 0 deletions compiler/lang/func.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,27 @@ void Func::codegenYield(Value *val, types::Type *type, BasicBlock *&block,
}
}

Value *Func::codegenYieldExpr(BasicBlock *&block) {
if (!gen)
throw exc::SeqException("yield expression in non-generator");

LLVMContext &context = block->getContext();
Function *suspFn = Intrinsic::getDeclaration(module, Intrinsic::coro_suspend);
Value *tok = ConstantTokenNone::get(context);
Value *final = ConstantInt::get(IntegerType::getInt1Ty(context), 0);
IRBuilder<> builder(block);
Value *susp = builder.CreateCall(suspFn, {tok, final});

block = BasicBlock::Create(block->getContext(), "", block->getParent());

SwitchInst *inst = builder.CreateSwitch(susp, suspend, 2);
inst->addCase(ConstantInt::get(IntegerType::getInt8Ty(context), 0), block);
inst->addCase(ConstantInt::get(IntegerType::getInt8Ty(context), 1), cleanup);

builder.SetInsertPoint(block);
return builder.CreateLoad(promise);
}

bool Func::isGen() { return yield != nullptr; }

std::vector<std::string> Func::getArgNames() { return argNames; }
Expand Down
98 changes: 88 additions & 10 deletions compiler/lang/patterns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,29 @@ void SeqPattern::resolveTypes(types::Type *type) {
getSrcInfo());
}

// Returns the appropriate character for the given logical index, respecting
// reverse complementation. Given `lenActual` should be non-negative.
static Value *indexIntoSeq(Value *ptr, Value *lenActual, Value *rc, Value *idx,
BasicBlock *block) {
LLVMContext &context = block->getContext();
IRBuilder<> builder(block);
Value *backIdx = builder.CreateSub(lenActual, idx);
backIdx = builder.CreateSub(backIdx, oneLLVM(context));

Value *charFwdPtr = builder.CreateGEP(ptr, idx);
Value *charRevPtr = builder.CreateGEP(ptr, backIdx);

Value *charFwd = builder.CreateLoad(charFwdPtr);
Value *charRev = builder.CreateLoad(charRevPtr);

GlobalVariable *table = types::ByteType::getByteCompTable(block->getModule());
charRev = builder.CreateZExt(charRev, builder.getInt64Ty());
charRev = builder.CreateInBoundsGEP(table, {builder.getInt64(0), charRev});
charRev = builder.CreateLoad(charRev);

return builder.CreateSelect(rc, charRev, charFwd);
}

static Value *codegenSeqMatchForSeq(const std::vector<char> &patterns,
BaseFunc *base, types::Type *type,
Value *val, BasicBlock *&block) {
Expand All @@ -330,14 +353,16 @@ static Value *codegenSeqMatchForSeq(const std::vector<char> &patterns,
Value *lenMatch = nullptr;
BasicBlock *startBlock = block;
IRBuilder<> builder(block);
Value *rc = builder.CreateICmpSLT(len, zeroLLVM(context));
Value *lenActual = builder.CreateSelect(rc, builder.CreateNeg(len), len);

// check lengths:
if (hasStar) {
Value *minLen = ConstantInt::get(seqIntLLVM(context), patterns.size() - 1);
lenMatch = builder.CreateICmpSGE(len, minLen);
lenMatch = builder.CreateICmpSGE(lenActual, minLen);
} else {
Value *expectedLen = ConstantInt::get(seqIntLLVM(context), patterns.size());
lenMatch = builder.CreateICmpEQ(len, expectedLen);
lenMatch = builder.CreateICmpEQ(lenActual, expectedLen);
}

block = BasicBlock::Create(
Expand All @@ -353,7 +378,7 @@ static Value *codegenSeqMatchForSeq(const std::vector<char> &patterns,
if (patterns[i] == '_')
continue;
Value *idx = ConstantInt::get(seqIntLLVM(context), i);
Value *sub = builder.CreateLoad(builder.CreateGEP(ptr, idx));
Value *sub = indexIntoSeq(ptr, lenActual, rc, idx, block);
Value *c = ConstantInt::get(IntegerType::getInt8Ty(context),
(uint64_t)patterns[i]);
Value *subRes = builder.CreateICmpEQ(sub, c);
Expand All @@ -366,11 +391,11 @@ static Value *codegenSeqMatchForSeq(const std::vector<char> &patterns,
if (patterns[i] == '_')
continue;
Value *idx = ConstantInt::get(seqIntLLVM(context), i);
idx = builder.CreateAdd(idx, len);
idx = builder.CreateAdd(idx, lenActual);
idx = builder.CreateSub(
idx, ConstantInt::get(seqIntLLVM(context), patterns.size()));

Value *sub = builder.CreateLoad(builder.CreateGEP(ptr, idx));
Value *sub = indexIntoSeq(ptr, lenActual, rc, idx, block);
Value *c = ConstantInt::get(IntegerType::getInt8Ty(context),
(uint64_t)patterns[i]);
Value *subRes = builder.CreateICmpEQ(sub, c);
Expand All @@ -383,7 +408,7 @@ static Value *codegenSeqMatchForSeq(const std::vector<char> &patterns,
if (patterns[i] == '_')
continue;
Value *idx = ConstantInt::get(seqIntLLVM(context), i);
Value *sub = builder.CreateLoad(builder.CreateGEP(ptr, idx));
Value *sub = indexIntoSeq(ptr, lenActual, rc, idx, block);
Value *c = ConstantInt::get(IntegerType::getInt8Ty(context),
(uint64_t)patterns[i]);
Value *subRes = builder.CreateICmpEQ(sub, c);
Expand Down Expand Up @@ -413,9 +438,13 @@ static Value *codegenSeqMatchForSeq(const std::vector<char> &patterns,
static Value *codegenSeqMatchForKmer(const std::vector<char> &patterns,
BaseFunc *base, types::KMer *type,
Value *val, BasicBlock *&block) {
static const unsigned BRUTE_MATCH_K_CUTOFF = 256;
static const unsigned BRUTE_MATCH_P_CUTOFF = 100;

LLVMContext &context = block->getContext();
Value *fail = ConstantInt::get(IntegerType::getInt1Ty(context), 0);
Value *succ = ConstantInt::get(IntegerType::getInt1Ty(context), 1);
Value *falseBool = ConstantInt::get(types::Bool->getLLVMType(context), 0);

if (patterns.empty())
return fail; // k-mer length must be at least 1
Expand Down Expand Up @@ -451,11 +480,59 @@ static Value *codegenSeqMatchForKmer(const std::vector<char> &patterns,
}

Type *llvmType = type->getLLVMType(context);

// if k is small and pattern is small, brute force matching is fastest:
if (hasStar && k <= BRUTE_MATCH_K_CUTOFF &&
patterns.size() <= BRUTE_MATCH_P_CUTOFF) {
types::KMer *k1Type = types::KMer::get(1);

BasicBlock *succBlock = block;
BasicBlock *failBlock = BasicBlock::Create(context, "", block->getParent());

IRBuilder<> builder(succBlock);
bool backIndex = false;

for (unsigned i = 0; i < patterns.size(); i++) {
const char c = patterns[i];
if (c == '_')
continue;
if (c == '\0') {
assert(!backIndex);
backIndex = true;
continue;
}
unsigned idx = backIndex ? (k + i - patterns.size()) : i;
Value *idxVal = ConstantInt::get(seqIntLLVM(context), idx);
Value *base = type->callMagic("__getitem__", {types::Int}, val, {idxVal},
succBlock, nullptr);
Value *expected =
k1Type->callMagic("__init__", {types::Byte}, nullptr,
{builder.getInt8(c)}, succBlock, nullptr);
Value *match = builder.CreateICmpEQ(base, expected);
succBlock = BasicBlock::Create(context, "", block->getParent());
builder.CreateCondBr(match, succBlock, failBlock);
builder.SetInsertPoint(succBlock);
}

block = BasicBlock::Create(context, "", block->getParent());
builder.CreateBr(block);

builder.SetInsertPoint(failBlock);
builder.CreateBr(block);

builder.SetInsertPoint(block);
PHINode *result = builder.CreatePHI(IntegerType::getInt1Ty(context), 2);
result->addIncoming(succ, succBlock);
result->addIncoming(fail, failBlock);
return result;
}

if (!hasStar) {
SeqExpr s(std::string(patterns.begin(), patterns.end()));
Value *expectedSeq = s.codegen(base, block);
Value *expectedKmer = type->callMagic("__init__", {types::Seq}, nullptr,
{expectedSeq}, block, nullptr);
Value *expectedKmer =
type->callMagic("__init__", {types::Seq, types::Bool}, nullptr,
{expectedSeq, falseBool}, block, nullptr);
IRBuilder<> builder(block);

if (!hasWildcard) {
Expand Down Expand Up @@ -488,8 +565,9 @@ static Value *codegenSeqMatchForKmer(const std::vector<char> &patterns,
SeqExpr sLeft(leftString);
Value *expectedSeqLeft = sLeft.codegen(base, block);
typeLeft = types::KMer::get(leftString.size());
expectedKmerLeft = typeLeft->callMagic("__init__", {types::Seq}, nullptr,
{expectedSeqLeft}, block, nullptr);
expectedKmerLeft =
typeLeft->callMagic("__init__", {types::Seq, types::Bool}, nullptr,
{expectedSeqLeft, falseBool}, block, nullptr);
}

if (!rightString.empty()) {
Expand Down
42 changes: 40 additions & 2 deletions compiler/types/funct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ void types::GenType::resume(Value *self, BasicBlock *block, BasicBlock *normal,
builder.CreateCall(resFn, self);
}

Value *types::GenType::promise(Value *self, BasicBlock *block) {
Value *types::GenType::promise(Value *self, BasicBlock *block, bool returnPtr) {
if (outType->is(types::Void))
return nullptr;

Expand All @@ -187,7 +187,15 @@ Value *types::GenType::promise(Value *self, BasicBlock *block) {
Value *ptr = builder.CreateCall(promFn, {self, aln, from});
ptr = builder.CreateBitCast(
ptr, PointerType::get(outType->getLLVMType(context), 0));
return builder.CreateLoad(ptr);
return returnPtr ? ptr : builder.CreateLoad(ptr);
}

void types::GenType::send(Value *self, Value *val, BasicBlock *block) {
Value *promisePtr = promise(self, block, /*returnPtr=*/true);
if (!promisePtr)
throw exc::SeqException("cannot send value to void generator");
IRBuilder<> builder(block);
builder.CreateStore(val, promisePtr);
}

void types::GenType::destroy(Value *self, BasicBlock *block) {
Expand Down Expand Up @@ -269,6 +277,36 @@ void types::GenType::initOps() {
}),
true);

addMethod("send",
new BaseFuncLite(
{this, outType}, Void,
[this](Module *module) {
const std::string name = "seq." + getName() + ".send";
Function *func = module->getFunction(name);

if (!func) {
LLVMContext &context = module->getContext();
func = cast<Function>(module->getOrInsertFunction(
name, Void->getLLVMType(context), getLLVMType(context),
outType->getLLVMType(context)));
func->setLinkage(GlobalValue::PrivateLinkage);
func->setDoesNotThrow();
func->addFnAttr(Attribute::AlwaysInline);

auto iter = func->arg_begin();
Value *self = iter++;
Value *val = iter;
BasicBlock *entry =
BasicBlock::Create(context, "entry", func);
send(self, val, entry);
IRBuilder<> builder(entry);
builder.CreateRetVoid();
}

return func;
}),
true);

addMethod(
"destroy",
new BaseFuncLite(
Expand Down
Loading