This repository has been archived by the owner on Dec 8, 2022. It is now read-only.
Releases: seq-lang/seq
Releases · seq-lang/seq
v0.11.0
v0.10.3
- Fix illegal instruction error on Linux.
v0.10.2
- Improved Python standard module compatibility
- htslib is now statically linked with runtime library, so an external htslib is no longer needed
v0.10.1
seqc
now correctly reads from stdin by default or when passed-
as input file- Other minor fixes
v0.10.0
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
)
- Run: Runs the program directly with the JIT (
- 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 unwrapOptional[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
andstaticlen
, as well as compile-time static expressions
- new compile-time
- 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
or234u615
- Uses
Int[N].__new__(str)
to parse such numbers
- Uses
- Binary representation:
010101b
- Digit separator:
123_456
or0001_0101b
- Custom suffixes:
123sfx
→int.__suffix_sfx__("123")
- Unsigned integers:
- Improved Float lexing:
- Custom suffixes:
123.sfx
→float.__suffix_sfx__("123.")
1e2
is parsed as a float, not as an integer with suffixe2
- Custom suffixes:
- Improved String handling:
- Custom prefixes:
pfx"hi"
→str.__prefix_pfx__[2]("hi")
(length si passed as a static integer)
- Custom prefixes:
- Better unpacking support:
- List unpacking:
[1, *args, 2]
ifargs
supports__iter__
- Set unpacking:
{1, *args, 2}
ifargs
supports__iter__
- Dictionary unpacking:
{a: b, **args}
ifargs
supports__iter__
that returnsTuple[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()]
- List unpacking:
- 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")
- integers, Booleans, ternary operator
- 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]]
forstart: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
functionprint
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 nowcase x | y
- Each
- 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]
andpyobj
forward their method calls- Support for custom atomic updates (
__atomic_op__
and__atomic_xchg__
)
v0.9.11
- 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