diff --git a/artiq/compiler/builtins.py b/artiq/compiler/builtins.py index 3e82f955f..9965f5284 100644 --- a/artiq/compiler/builtins.py +++ b/artiq/compiler/builtins.py @@ -67,6 +67,10 @@ class TStr(types.TMono): def __init__(self): super().__init__("str") +class TBytes(types.TMono): + def __init__(self): + super().__init__("bytes") + class TList(types.TMono): def __init__(self, elt=None): if elt is None: @@ -137,6 +141,9 @@ def fn_float(): def fn_str(): return types.TConstructor(TStr()) +def fn_bytes(): + return types.TConstructor(TBytes()) + def fn_list(): return types.TConstructor(TList()) @@ -236,6 +243,9 @@ def is_float(typ): def is_str(typ): return types.is_mono(typ, "str") +def is_bytes(typ): + return types.is_mono(typ, "bytes") + def is_numeric(typ): typ = typ.find() return isinstance(typ, types.TMono) and \ @@ -254,7 +264,12 @@ def is_array(typ, elt=None): return types.is_mono(typ, "array") def is_listish(typ, elt=None): - return is_list(typ, elt) or is_array(typ, elt) or (elt is None and is_str(typ)) + if is_list(typ, elt) or is_array(typ, elt): + return True + elif elt is None: + return is_str(typ) or is_bytes(typ) + else: + return False def is_range(typ, elt=None): if elt is not None: @@ -277,7 +292,7 @@ def is_iterable(typ): def get_iterable_elt(typ): if is_iterable(typ): return typ.find()["elt"].find() - elif is_str(typ): + elif is_str(typ) or is_bytes(typ): return TInt(types.TValue(8)) else: assert False diff --git a/artiq/compiler/embedding.py b/artiq/compiler/embedding.py index b2fd51061..052a5d737 100644 --- a/artiq/compiler/embedding.py +++ b/artiq/compiler/embedding.py @@ -200,6 +200,9 @@ class ASTSynthesizer: elif isinstance(value, str): return asttyped.StrT(s=value, ctx=None, type=builtins.TStr(), loc=self._add(repr(value))) + elif isinstance(value, bytes): + return asttyped.StrT(s=value, ctx=None, type=builtins.TBytes(), + loc=self._add(repr(value))) elif isinstance(value, list): begin_loc = self._add("[") elts = [] diff --git a/artiq/compiler/prelude.py b/artiq/compiler/prelude.py index f50e4f2fa..f451b8a62 100644 --- a/artiq/compiler/prelude.py +++ b/artiq/compiler/prelude.py @@ -11,6 +11,8 @@ def globals(): "bool": builtins.fn_bool(), "int": builtins.fn_int(), "float": builtins.fn_float(), + "str": builtins.fn_str(), + "bytes": builtins.fn_bytes(), "list": builtins.fn_list(), "array": builtins.fn_array(), "range": builtins.fn_range(), diff --git a/artiq/compiler/transforms/asttyped_rewriter.py b/artiq/compiler/transforms/asttyped_rewriter.py index 3c840673e..4c3112be6 100644 --- a/artiq/compiler/transforms/asttyped_rewriter.py +++ b/artiq/compiler/transforms/asttyped_rewriter.py @@ -331,8 +331,13 @@ class ASTTypedRewriter(algorithm.Transformer): n=node.n, loc=node.loc) def visit_Str(self, node): - return asttyped.StrT(type=builtins.TStr(), - s=node.s, + if isinstance(node.s, str): + typ = builtins.TStr() + elif isinstance(node.s, bytes): + typ = builtins.TBytes() + else: + assert False + return asttyped.StrT(type=typ, s=node.s, begin_loc=node.begin_loc, end_loc=node.end_loc, loc=node.loc) def visit_Name(self, node): diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index 835cf976b..0bb73ef05 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -1054,7 +1054,7 @@ class LLVMIRGenerator: lloperand = self.map(operand) if i == 0 and insn.op == "printf" or i == 1 and insn.op == "rtio_log": lloperands.append(self.llbuilder.extract_value(lloperand, 0)) - elif builtins.is_str(operand.type): + elif builtins.is_str(operand.type) or builtins.is_bytes(operand.type): lloperands.append(self.llbuilder.extract_value(lloperand, 1)) lloperands.append(self.llbuilder.extract_value(lloperand, 0)) else: @@ -1434,7 +1434,7 @@ class LLVMIRGenerator: elif builtins.is_float(typ): assert isinstance(value, float), fail_msg return ll.Constant(llty, value) - elif builtins.is_str(typ): + elif builtins.is_str(typ) or builtins.is_bytes(typ): assert isinstance(value, (str, bytes)), fail_msg if isinstance(value, str): as_bytes = value.encode("utf-8") diff --git a/artiq/test/lit/inferencer/unify.py b/artiq/test/lit/inferencer/unify.py index bb7fd9241..5ccbc6b70 100644 --- a/artiq/test/lit/inferencer/unify.py +++ b/artiq/test/lit/inferencer/unify.py @@ -57,6 +57,9 @@ lambda x, y=1: x k = "x" # CHECK-L: k:str +ka = b"x" +# CHECK-L: ka:bytes + l = array([1]) # CHECK-L: l:numpy.array(elt=numpy.int?)