Seq Versions Save

A high-performance, Pythonic language for bioinformatics

v0.11.0

2 years ago
  • Full OpenMP support (docs)
  • New PEG parser to replace original OCaml/Menhir parser
  • Upgrade to LLVM 12 (from LLVM 6)
  • Types can now be passed as function arguments

v0.10.3

2 years ago
  • Fix illegal instruction error on Linux.

v0.10.2

2 years ago
  • Improved Python standard module compatibility
  • htslib is now statically linked with runtime library, so an external htslib is no longer needed

v0.10.1

3 years ago
  • seqc now correctly reads from stdin by default or when passed - as input file
  • Other minor fixes

v0.10.0

3 years ago

Overview

Version 0.10 brings a slew of improvements to the language and compiler, including:

  • Nearly all of Python’s syntax is now supported, including empty collections ([],{}), lambda functions (lambda), *args/**kwargs, None and much more
  • Compiler error messages now pinpoint exactly where an error occured with compile-time backtraces
  • Runtime exceptions now include backtraces with file names and line numbers in debug mode
  • GDB and LLDB support
  • Various syntax updates to further close the gap with Python
  • Numerous standard library improvements

Detailed changes

seqc

The seqc command’s syntax and default behavior has changed in v0.10:

  • Default is now “debug” mode, which disables most compiler optimizations but now shows full backtraces with file and line information, and allows for debugging with GDB/LLDB.
  • Optimizations can be enable with “release” mode via the -release flag.
  • seqc has three modes to choose from (use -help on any of these for more info):
    • Run: Runs the program directly with the JIT (seqc run)
    • Build: Compile the program to an executable, object file or LLVM IR (seqc build)
    • Doc: Generate documentation for a program based on docstrings (seqc doc)
  • If you just want to run a program: seqc run program.seq

Type system

Seq 0.10 ships with the completely revamped bi-directional type system. Here is a short gist of the new type system in action:

a = []
for i in range(3):
    a.append(i)
print a # it is a List[int] with [1, 2, 3]

b = None if len(a) else [1, 3]  # b is Optional[List[int]]
b.append(3)  # either appends 3 or raises an error if b is None

def foo[T: int, TA = int](a, b: Optional[Function[TA, TA]] = None):
    if isinstance(TA, int):
        if T < 4:
            return a
        else:
            return 1.1
    else:
      return f'modified {b(a)+T}'
def adder(a, b):
    return a + b ** 2
print foo[1](1)  # 1 of type int
print foo[5](1)  # 1.1 of type float
print foo[1](2, adder(3, ...))  # 'modified 8' of type string

Major highlights:

  • Automatic type deduction
    a = []
    a.append(1)
    print a
    
  • Improved Optional[T] handling (assignments, if-else expressions, calls and dot-expressions automatically wrap or unwrap Optional[T])
    a = None
    a = 5 # a is now Optional[int]
    a + 1 # 6 as a gets unwrapped
    b = 1 if foo() else None # b is Optional[int]
    
  • Compile-time static integer types and expressions:
    def foo[N: int]():
      print N
    foo[4]() # 4
    
    # static integers can be passed from the command line:
    # seqc -DK=5 foo.seq
    k = Kmer[K] # becomes Kmer[5]
    k = Kmer[1 if K > 2 else 4] # also works as this is a static expression
    
    if K > 3:
       # <something>; compiled only if K > 3 at the compiile-time
    else:
       # <something else>
    
  • Compile-time type checks
    • new compile-time isinstance, hasattr and staticlen, as well as compile-time static expressions
  • Improved support for partial functions

Improved Python support

All Python objects are not first-class Seq objects:

from python import numpy as np
a = np.array(2, 2)
print a[0,1].pow()

Syntax changes

Tuple classes:

@tuple
class Foo:  # instead of type Foo(x: T)
    x: T

Type extension:

@extend
class Foo:  # instead of extend Foo

Auto-deduction of self type:

class Foo[T]:
   def bar(self, x):  # instead of bar(self: Foo[T], x)

Support for lambdas:

print list(map(range(5), lambda x: x + 1))  # [1, 2, 3, 4, 5]

Python 3 print function:

print(a, b, sep='~', end='!', file=fo)
print a  # this is still supported

Mypy-style naming:

List[int] # not list[int]
Dict[int, Tuple[int]] # not dict[int,tuple[int]]
Callable[[int, int], void] # not function[void,int,int]

Relative and recursive import support:

from .. import foo

C, Python and LLVM imports:

from C import pow(float, float) -> float  # instead of cimport pow
from C import library.foo(int)
from python import numpy
from python import os.system(str) -> str  # instead of pyimport

@python
def foo():  # instead of pydef foo()
    print sys.path

@llvm
def bar(x: T) -> Ptr[byte]:
    %0 = {=T}* nullptr
    ret i8* %0

Walrus (assign) expression:

if (x := foo()):
    print x

loop-else support

for i in bar():  pass
else:  print 'no break'

while foo():  pass
else:  print 'no break'

Other changes

  • Improved Ints:
    • Unsigned integers: 123u
    • Fixed-width integers: 12i14 or 234u615
      • Uses Int[N].__new__(str) to parse such numbers
    • Binary representation: 010101b
    • Digit separator: 123_456 or 0001_0101b
    • Custom suffixes: 123sfxint.__suffix_sfx__("123")
  • Improved Float lexing:
    • Custom suffixes: 123.sfxfloat.__suffix_sfx__("123.")
    • 1e2 is parsed as a float, not as an integer with suffix e2
  • Improved String handling:
    • Custom prefixes: pfx"hi"str.__prefix_pfx__[2]("hi") (length si passed as a static integer)
  • Better unpacking support:
    • List unpacking: [1, *args, 2] if args supports __iter__
    • Set unpacking: {1, *args, 2} if args supports __iter__
    • Dictionary unpacking: {a: b, **args} if args supports __iter__ that returns Tuple[K, V]
    • Call unpacking: foo(a, *args, **kwargs)
      • args must be a tuple (lists and named t won’t work). Named tuples are OK.
      • kwargs must be a named tuple (@tuple class)
    • Support variable unpacking in for loops and comprehensions: for i, *_, (k, l) in foo or [a(b) for _, b in c.items()]
  • Static evaluation
    • integers, Booleans, ternary operator a if b else c, unary operators [not,-], binary operators [+,-,*,//,%], conditional operators [==,!=,<,<=,>,>=,and,or] and the following static calls:
      • staticlen(tuple)
      • isinstance(var, type)
      • hasattr(type, "attr")
      • compile_error("str")
  • Named and default argument support for partial functions: def foo(a, b, c=1): … ; p = foo(1, …, …); p(b=2)
  • All partial functions must be explicitly annotated with (no more auto-partialization except in pipe expression)
  • Unified slice type Slice[Optional[int],Optional[int,Optional[int]] for start:stop:step
  • Assign (walrus) expression: if a := foo(): …
    • Valid only in its own block
    • Not allowed in a short-circuiting expressions: if a or (b := foo()) won’t compile
  • __ptr__ is a proper expression now
  • Assign statements support type annotations: a: List[int] = []
  • Proper print function
    • print followed by a whitespace is a statement; print that is not is a identifier
  • Improved assert statement: assert foo(), f"Failed! {bar}"
  • Heterogeneous tuple iteration in for loop:
    • a = (1, 's', 5.5); for i in a: print(i)
    • Each iteration is a separate block
    • User needs to ensure that enclosing types are not incorrectly used
    • Cannot be composed with other iterators (e.g. for i, a in enumerate((1, 's')): …)
  • Improved match statement:
    • Each case checks for correct type; if a expression type is incorrect, the corresponding case is ignored
    • Support custom matching via __match__ magic
    • case x or y is now case x | y
  • Better import support
    • Support for recursive importing
    • Support for Python-style import execution (order of import execution is decided at runtime)
  • New tuple magic: __dict__(self) -> List[str] that returns list of class member names
  • __contains__ works on heterogeneous tuples
  • Each module exposes __name__
  • Improved a is b check
  • Better slices (via Slice())
  • Optional[T] and pyobj forward their method calls
  • Support for custom atomic updates (__atomic_op__ and __atomic_xchg__)

v0.9.11

3 years ago
  • Inter-sequence alignment kernel now portable by choosing SIMD instruction set at runtime
  • SAM/BAM error handling improvements and API additions
  • Bug fixes:
    • Fixed an issue caused by raising exceptions from properties
    • Fixed an inter-sequence alignment flush issue

v0.9.10

3 years ago
  • Build / install simplifications

v0.9.9

3 years ago
  • Fix GC collecting from unknown thread error
  • Update build

v0.9.8

3 years ago
  • New parsers for VCF, BED and FAI files
  • Various standard library fixes and improvements
  • Build simplification

v0.9.7

3 years ago