Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: c75fd6bc88e1
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: abbc87e981e8
Choose a head ref
  • 2 commits
  • 4 files changed
  • 1 contributor

Commits on May 29, 2015

  1. Update .gitignore.

    whitequark committed May 29, 2015
    Copy the full SHA
    74080f2 View commit details
  2. Add new type inferencer.

    whitequark committed May 29, 2015
    1
    Copy the full SHA
    abbc87e View commit details
Showing with 469 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +53 −0 artiq/py2llvm/asttyped.py
  3. +189 −0 artiq/py2llvm/types.py
  4. +226 −0 artiq/py2llvm/typing.py
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ __pycache__
*.bin
*.elf
*.fbi
*.pyc
soc/runtime/service_table.h
doc/manual/_build
/build
53 changes: 53 additions & 0 deletions artiq/py2llvm/asttyped.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""
The typedtree module exports the PythonParser AST enriched with
typing information.
"""

from pythonparser import ast
from pythonparser.algorithm import Visitor as ASTVisitor

class commontyped(ast.commonloc):
"""A mixin for typed AST nodes."""

_types = ('type',)

def _reprfields(self):
return self._fields + self._locs + self._types

class scoped(object):
"""
:ivar typing_env: (dict with string keys and :class:`.types.Type` values)
map of variable names to variable types
:ivar globals_in_scope: (set of string keys)
list of variables resolved as globals
"""

class ClassDefT(ast.ClassDef, scoped):
pass

class FunctionDefT(ast.FunctionDef, scoped):
pass

class LambdaT(ast.Lambda, scoped):
pass

class DictCompT(ast.DictComp, scoped):
pass

class ListCompT(ast.ListComp, scoped):
pass

class SetCompT(ast.SetComp, scoped):
pass

class argT(ast.arg, commontyped):
pass

class NumT(ast.Num, commontyped):
pass

class NameT(ast.Name, commontyped):
pass

class NameConstantT(ast.NameConstant, commontyped):
pass
189 changes: 189 additions & 0 deletions artiq/py2llvm/types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
"""
The :mod:`types` module contains the classes describing the types
in :mod:`asttyped`.
"""

import string

def genalnum():
ident = ["a"]
while True:
yield "".join(ident)
pos = len(ident) - 1
while pos >= 0:
cur_n = string.ascii_lowercase.index(ident[pos])
if cur_n < 26:
ident[pos] = string.ascii_lowercase[cur_n + 1]
break
else:
ident[pos] = "a"
pos -= 1
if pos < 0:
ident = "a" + ident

class UnificationError(Exception):
def __init__(self, typea, typeb):
self.typea, self.typeb = typea, typeb


class Type(object):
pass

class TVar(Type):
"""
A type variable.
In effect, the classic union-find data structure is intrusively
folded into this class.
"""

def __init__(self):
self.parent = self

def find(self):
if self.parent is self:
return self
else:
root = self.parent.find()
self.parent = root # path compression
return root

def unify(self, other):
other = other.find()

if self.parent is self:
self.parent = other
else:
self.find().unify(other)

def __repr__(self):
if self.parent is self:
return "TVar(%d)" % id(self)
else:
return repr(self.find())

# __eq__ and __hash__ are not overridden and default to
# comparison by identity. Use .find() explicitly before
# any lookups or comparisons.

class TMono(Type):
"""A monomorphic type, possibly parametric."""

def __init__(self, name, params={}):
self.name, self.params = name, params

def find(self):
return self

def unify(self, other):
if isinstance(other, TMono) and self.name == other.name:
assert self.params.keys() == other.params.keys()
for param in self.params:
self.params[param].unify(other.params[param])
else:
raise UnificationError(self, other)

def __repr__(self):
return "TMono(%s, %s)" % (repr(self.name), repr(self.params))

def __eq__(self, other):
return isinstance(other, TMono) and \
self.name == other.name and \
self.params == other.params

def __ne__(self, other):
return not (self == other)

class TTuple(Type):
"""A tuple type."""

def __init__(self, elts=[]):
self.elts = elts

def find(self):
return self

def unify(self, other):
if isinstance(other, TTuple) and len(self.elts) == len(other.elts):
for selfelt, otherelt in zip(self.elts, other.elts):
selfelt.unify(otherelt)
else:
raise UnificationError(self, other)

def __repr__(self):
return "TTuple(%s)" % (", ".join(map(repr, self.elts)))

def __eq__(self, other):
return isinstance(other, TTuple) and \
self.elts == other.elts

def __ne__(self, other):
return not (self == other)

class TValue(Type):
"""
A type-level value (such as the integer denoting width of
a generic integer type.
"""

def __init__(self, value):
self.value = value

def find(self):
return self

def unify(self, other):
if self != other:
raise UnificationError(self, other)

def __repr__(self):
return "TValue(%s)" % repr(self.value)

def __eq__(self, other):
return isinstance(other, TValue) and \
self.value == other.value

def __ne__(self, other):
return not (self == other)

def TBool():
"""A boolean type."""
return TMono("bool")

def TInt(width=TVar()):
"""A generic integer type."""
return TMono("int", {"width": width})

def TFloat():
"""A double-precision floating point type."""
return TMono("float")


class TypePrinter(object):
"""
A class that prints types using Python-like syntax and gives
type variables sequential alphabetic names.
"""

def __init__(self):
self.gen = genalnum()
self.map = {}

def name(self, typ):
typ = typ.find()
if isinstance(typ, TVar):
if typ not in self.map:
self.map[typ] = "'%s" % next(self.gen)
return self.map[typ]
elif isinstance(typ, TMono):
return "%s(%s)" % (typ.name, ", ".join(
["%s=%s" % (k, self.name(typ.params[k])) for k in typ.params]))
elif isinstance(typ, TTuple):
if len(typ.elts) == 1:
return "(%s,)" % self.name(typ.elts[0])
else:
return "(%s)" % ", ".join(list(map(self.name, typ.elts)))
elif isinstance(typ, TValue):
return repr(typ.value)
else:
assert False
Loading