From 94daf144ab74148772c4854b06f685eb5769a72c Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sun, 18 Feb 2024 13:28:06 +0900 Subject: [PATCH] add poise installing --- ergup.er | 41 +- ergup.py | 1234 +++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 889 insertions(+), 386 deletions(-) diff --git a/ergup.er b/ergup.er index f02ebfd..3e65606 100644 --- a/ergup.er +++ b/ergup.er @@ -6,6 +6,7 @@ sys = pyimport "sys" os = pyimport "os" io = pyimport "io" su = pyimport "shutil" +sub = pyimport "subprocess" homedir = os.path.expanduser! "~" erg_dir = homedir + "/.erg" @@ -17,10 +18,10 @@ if! os.path.exists!(erg_dir), do!: answer = input!() if! answer == "y": do!: - print! "removing \{erg_dir} ..." + print! "Removing \{erg_dir} ..." su.rmtree! erg_dir do!: - print! "aborting installation" + print! "Aborting installation" exit 1 os.mkdir! erg_dir @@ -41,26 +42,46 @@ filename = match sys.platform: _ -> "erg-x86_64-unknown-linux-gnu.tar.gz" url = "https://github.com/erg-lang/erg/releases/download/\{latest_version}/\{filename}" -print! "downloading \{url} ..." +print! "Downloading \{url} ..." stream = urllib.request.urlopen!(url) if! sys.platform == "win32": do!: - print! "extracting \{filename} ..." + print! "Extracting \{filename} ..." bytesio = io.BytesIO! stream.read!() zipfile = zf.ZipFile! bytesio zipfile.extractall! erg_tmp_dir zipfile.close!() - su.move! "\{erg_tmp_dir}/erg.exe", "\{erg_bin_dir}/erg.exe" - su.move! "\{erg_tmp_dir}/lib", "\{erg_dir}/lib" + discard su.move! "\{erg_tmp_dir}/erg.exe", "\{erg_bin_dir}/erg.exe" + discard su.move! "\{erg_tmp_dir}/lib", "\{erg_dir}/lib" su.rmtree! erg_tmp_dir do!: - print! "extracting \{filename} ..." + print! "Extracting \{filename} ..." tarfile = tf.open!(fileobj:=stream, mode:="r|gz") tarfile.extractall! erg_tmp_dir tarfile.close!() - su.move! "\{erg_tmp_dir}/erg", "\{erg_bin_dir}/erg" - su.move! "\{erg_tmp_dir}/lib", "\{erg_dir}/lib" + discard su.move! "\{erg_tmp_dir}/erg", "\{erg_bin_dir}/erg" + discard su.move! "\{erg_tmp_dir}/lib", "\{erg_dir}/lib" su.rmtree! erg_tmp_dir -print! "please add `.erg` to your PATH by running `export PATH=$PATH:\{erg_bin_dir}` and `export ERG_PATH=\{erg_dir}`" +print! "erg installed successfully" + +poise_git_url = "https://github.com/erg-lang/poise.git" +print! "Cloning poise (erg package manager) ..." +if! not(os.path.exists!(erg_tmp_dir)), do!: + os.mkdir! erg_tmp_dir +os.chdir! erg_tmp_dir +res = sub.run! ["git", "clone", poise_git_url], capture_output:=True +if! res.returncode != 0, do!: + panic "Failed to clone poise repo" +os.chdir! "poise" +print! "Building poise ..." +res2 = sub.run! ["erg", "src/main.er", "--", "install"], capture_output:=True +if! res2.returncode != 0, do!: + assert res2.stderr in Bytes + panic "Failed to install poise: \{res2.stderr.decode()}" +print! "poise installed successfully" +os.chdir! ".." +su.rmtree! "poise" + +print! "Please add `.erg` to your PATH by running `export PATH=$PATH:\{erg_bin_dir}` and `export ERG_PATH=\{erg_dir}`" diff --git a/ergup.py b/ergup.py index f53bad6..cc413c1 100644 --- a/ergup.py +++ b/ergup.py @@ -4,22 +4,29 @@ def if__(cond, then, else_=lambda: None): else: return else_() + def for__(iterable, body): for i in iterable: body(i) + def while__(cond_block, body): while cond_block(): body() + def with__(obj, body): obj.__enter__() - body(e) + body(obj) obj.__exit__() + def discard__(obj): pass +def assert__(test, msg=None): + assert test, msg + def then__(x, f): if x == None or x == NotImplemented: return x @@ -27,143 +34,456 @@ def then__(x, f): return f(x) # from typing import TypeVar, Union, _SpecialForm, _type_check + class Error: def __init__(self, message): self.message = message + # T = TypeVar("T") # @_SpecialForm -def Result(self, parameters): - """Result type. +# def Result(self, parameters): +# """Result type. +# +# Result[T] is equivalent to Union[T, Error]. +# """ +# arg = _type_check(parameters, f"{self} requires a single type.") +# return [arg, Error] - Result[T] is equivalent to Union[T, Error]. - """ - # arg = _type_check(parameters, f"{self} requires a single type.") - return [arg, Error] def is_ok(obj) -> bool: return not isinstance(obj, Error) +# from collections.abc import Iterable, Sequence, Iterator, Container + + +class Range: + def __init__(self, start, end): + self.start = start + self.end = end + + def __contains__(self, item): + pass + + @staticmethod + def from_slice(slice): + pass + + def into_slice(self): + pass + + def __getitem__(self, item): + res = self.start + item + if res in self: + return res + else: + raise IndexError("Index out of range") + + # TODO: for Str, etc. + def __len__(self): + if self.start in self: + if self.end in self: + # len(1..4) == 4 + return self.end - self.start + 1 + else: + # len(1..<4) == 3 + return self.end - self.start + else: + if self.end in self: + # len(1<..4) == 3 + return self.end - self.start + else: + # len(1<..<4) == 2 + return self.end - self.start - 2 + + def __iter__(self): + return RangeIterator(rng=self) + + +# Sequence.register(Range) +# Container.register(Range) +# Iterable.register(Range) + + +# represents `start<..end` +class LeftOpenRange(Range): + def __contains__(self, item): + return self.start < item <= self.end + + +# represents `start.. 0: + s += ", " + s += str(arg) + s += "]" + return s + def __repr__(self): + return self.__str__() + +class FakeGenericAlias: + __origin__: type + __args__: list # list[type] + def __init__(self, origin, *args): + self.__origin__ = origin + self.__args__ = args +try: + from types import GenericAlias +except ImportError: + GenericAlias = FakeGenericAlias + +def is_type(x) -> bool: + return isinstance(x, (type, FakeGenericAlias, GenericAlias, UnionType)) + +# The behavior of `builtins.isinstance` depends on the Python version. +def _isinstance(obj, classinfo) -> bool: + if isinstance(classinfo, (FakeGenericAlias, GenericAlias, UnionType)): + if classinfo.__origin__ == Union: + return any(_isinstance(obj, t) for t in classinfo.__args__) + else: + return isinstance(obj, classinfo.__origin__) + else: + try: + return isinstance(obj, classinfo) + except: + return False + +class MutType: + value: object + + + + + + +from collections import namedtuple + +# (elem in y) == contains_operator(y, elem) +def contains_operator(y, elem) -> bool: + if hasattr(elem, "type_check"): + return elem.type_check(y) + elif isinstance(y, UnionType): + return any([contains_operator(t, elem) for t in y.__args__]) + # 1 in Int + elif is_type(y): + if _isinstance(elem, y): + return True + elif hasattr(y, "generic_try_new"): + return is_ok(y.generic_try_new(elem, y)) + elif hasattr(y, "try_new") and is_ok(y.try_new(elem)): + return True + elif hasattr(y, "__origin__") and hasattr(y.__origin__, "type_check"): + return y.__origin__.type_check(elem, y) + # TODO: trait check + return False + # [1] in [Int] + elif ( + _isinstance(y, list) + and _isinstance(elem, list) + and (len(y) == 0 or is_type(y[0]) or _isinstance(y[0], Range)) + ): + type_check = all(map(lambda x: contains_operator(x[0], x[1]), zip(y, elem))) + len_check = len(elem) <= len(y) + return type_check and len_check + # (1, 2) in (Int, Int) + elif ( + _isinstance(y, tuple) + and _isinstance(elem, tuple) + and (len(y) == 0 or is_type(y[0]) or _isinstance(y[0], Range)) + ): + if not hasattr(elem, "__iter__"): + return False + type_check = all(map(lambda x: contains_operator(x[0], x[1]), zip(y, elem))) + len_check = len(elem) <= len(y) + return type_check and len_check + # {1: 2} in {Int: Int} + elif ( + _isinstance(y, dict) + and _isinstance(elem, dict) + and (len(y) == 0 or is_type(next(iter(y.keys())))) + ): + if len(y) == 1: + key = next(iter(y.keys())) + key_check = all([contains_operator(key, el) for el in elem.keys()]) + value = next(iter(y.values())) + value_check = all([contains_operator(value, el) for el in elem.values()]) + return key_check and value_check + type_check = True # TODO: + len_check = True # It can be True even if either elem or y has the larger number of elems + return type_check and len_check + elif _isinstance(elem, list): + + return contains_operator(y, Array(elem)) + elif callable(elem): + # TODO: + return callable(y) + else: + return elem in y + + + + class Int(int): - def try_new(i): # -> Result[Nat] + def try_new(i): # -> Result[Nat] if isinstance(i, int): - Int(i) + return Int(i) + else: + return Error("not an integer") + + def bit_count(self): + if hasattr(int, "bit_count"): + return int.bit_count(self) else: - Error("not an integer") + return bin(self).count("1") + def succ(self): return Int(self + 1) + def pred(self): return Int(self - 1) + def mutate(self): return IntMut(self) + def __add__(self, other): return then__(int.__add__(self, other), Int) - def __radd__(self, other): - return then__(int.__add__(other, self), Int) + def __sub__(self, other): return then__(int.__sub__(self, other), Int) - def __rsub__(self, other): - return then__(int.__sub__(other, self), Int) + def __mul__(self, other): return then__(int.__mul__(self, other), Int) - def __rmul__(self, other): - return then__(int.__mul__(other, self), Int) + def __div__(self, other): return then__(int.__div__(self, other), Int) - def __rdiv__(self, other): - return then__(int.__div__(other, self), Int) + def __floordiv__(self, other): return then__(int.__floordiv__(self, other), Int) - def __rfloordiv__(self, other): - return then__(int.__floordiv__(other, self), Int) + def __pow__(self, other): return then__(int.__pow__(self, other), Int) + def __rpow__(self, other): return then__(int.__pow__(other, self), Int) -class IntMut(): # inherits Int + def __pos__(self): + return self + + def __neg__(self): + return then__(int.__neg__(self), Int) + + +class IntMut(MutType): # inherits Int value: Int def __init__(self, i): self.value = Int(i) + + def __int__(self): + return self.value.__int__() + + def __float__(self): + return self.value.__float__() + def __repr__(self): return self.value.__repr__() + + def __hash__(self): + return self.value.__hash__() + def __eq__(self, other): - if isinstance(other, Int): - return self.value == other - else: + if isinstance(other, MutType): return self.value == other.value - def __ne__(self, other): - if isinstance(other, Int): - return self.value != other else: + return self.value == other + + def __ne__(self, other): + if isinstance(other, MutType): return self.value != other.value - def __le__(self, other): - if isinstance(other, Int): - return self.value <= other else: + return self.value != other + + def __le__(self, other): + if isinstance(other, MutType): return self.value <= other.value - def __ge__(self, other): - if isinstance(other, Int): - return self.value >= other else: + return self.value <= other + + def __ge__(self, other): + if isinstance(other, MutType): return self.value >= other.value - def __lt__(self, other): - if isinstance(other, Int): - return self.value < other else: + return self.value >= other + + def __lt__(self, other): + if isinstance(other, MutType): return self.value < other.value - def __gt__(self, other): - if isinstance(other, Int): - return self.value > other else: + return self.value < other + + def __gt__(self, other): + if isinstance(other, MutType): return self.value > other.value - def __add__(self, other): - if isinstance(other, Int): - return IntMut(self.value + other) else: + return self.value > other + + def __add__(self, other): + if isinstance(other, MutType): return IntMut(self.value + other.value) - def __sub__(self, other): - if isinstance(other, Int): - return IntMut(self.value - other) else: + return IntMut(self.value + other) + + def __sub__(self, other): + if isinstance(other, MutType): return IntMut(self.value - other.value) - def __mul__(self, other): - if isinstance(other, Int): - return IntMut(self.value * other) else: + return IntMut(self.value - other) + + def __mul__(self, other): + if isinstance(other, MutType): return IntMut(self.value * other.value) + else: + return IntMut(self.value * other) + def __floordiv__(self, other): - if isinstance(other, Int): + if isinstance(other, MutType): + return IntMut(self.value // other.value) + else: return IntMut(self.value // other) + + def __truediv__(self, other): + if isinstance(other, MutType): + return IntMut(self.value / other.value) else: - return IntMut(self.value // other.value) + return IntMut(self.value / other) + def __pow__(self, other): - if isinstance(other, Int): - return IntMut(self.value ** other) + if isinstance(other, MutType): + return IntMut(self.value**other.value) else: - return IntMut(self.value ** other.value) + return IntMut(self.value**other) + + def __pos__(self): + return self + + def __neg__(self): + return IntMut(-self.value) + + def update(self, f): + self.value = Int(f(self.value)) + def inc(self, i=1): self.value = Int(self.value + i) + def dec(self, i=1): self.value = Int(self.value - i) + def succ(self): return self.value.succ() + def pred(self): return self.value.pred() - # don't unify with the above line + # don't unify with the above line + class Nat(Int): - def try_new(i): # -> Result[Nat] + def __init__(self, i): + if int(i) < 0: + raise ValueError("Nat can't be negative: {}".format(i)) + + def try_new(i): # -> Result[Nat] if i >= 0: return Nat(i) else: - return Error("Nat can't be negative") + return Error("Nat can't be negative: {}".format(i)) def times(self, f): for _ in range(self): @@ -174,76 +494,119 @@ def saturating_sub(self, other): return self - other else: return 0 + def mutate(self): return NatMut(self) + def __add__(self, other): return then__(super().__add__(other), Nat) + def __mul__(self, other): return then__(super().__mul__(other), Nat) -class NatMut(IntMut): # and Nat + def __pos__(self): + return self + + +class NatMut(IntMut): # and Nat value: Nat def __init__(self, n: Nat): + if int(n) < 0: + raise ValueError("Nat can't be negative: {}".format(n)) self.value = n + + def __int__(self): + return self.value.__int__() + + def __float__(self): + return self.value.__float__() + def __repr__(self): return self.value.__repr__() + + def __hash__(self): + return self.value.__hash__() + def __eq__(self, other): - if isinstance(other, int): - return self.value == other - else: + if isinstance(other, MutType): return self.value == other.value - def __ne__(self, other): - if isinstance(other, int): - return self.value != other else: + return self.value == other + + def __ne__(self, other): + if isinstance(other, MutType): return self.value != other.value - def __le__(self, other): - if isinstance(other, int): - return self.value <= other else: + return self.value != other + + def __le__(self, other): + if isinstance(other, MutType): return self.value <= other.value - def __ge__(self, other): - if isinstance(other, int): - return self.value >= other else: + return self.value <= other + + def __ge__(self, other): + if isinstance(other, MutType): return self.value >= other.value - def __lt__(self, other): - if isinstance(other, int): - return self.value < other else: + return self.value >= other + + def __lt__(self, other): + if isinstance(other, MutType): return self.value < other.value - def __gt__(self, other): - if isinstance(other, int): - return self.value > other else: + return self.value < other + + def __gt__(self, other): + if isinstance(other, MutType): return self.value > other.value - def __add__(self, other): - if isinstance(other, Nat): - return NatMut(self.value + other) else: + return self.value > other + + def __add__(self, other): + if isinstance(other, MutType): return NatMut(self.value + other.value) - def __radd__(self, other): - if isinstance(other, Nat): - return Nat(other + self.value) else: + return NatMut(self.value + other) + + def __radd__(self, other): + if isinstance(other, MutType): return Nat(other.value + self.value) - def __mul__(self, other): - if isinstance(other, Nat): - return NatMut(self.value * other) else: + return Nat(other + self.value) + + def __mul__(self, other): + if isinstance(other, MutType): return NatMut(self.value * other.value) + else: + return NatMut(self.value * other) + def __rmul__(self, other): - if isinstance(other, Nat): + if isinstance(other, MutType): + return Nat(other.value * self.value) + else: return Nat(other * self.value) + + def __truediv__(self, other): + if isinstance(other, MutType): + return NatMut(self.value / other.value) else: - return Nat(other.value * self.value) + return NatMut(self.value / other) + def __pow__(self, other): - if isinstance(other, Nat): - return NatMut(self.value ** other) + if isinstance(other, MutType): + return NatMut(self.value**other.value) else: - return NatMut(self.value ** other.value) - def try_new(i): # -> Result[Nat] + return NatMut(self.value**other) + + def __pos__(self): + return self + + def update(self, f): + self.value = Nat(f(self.value)) + + def try_new(i): # -> Result[Nat] if i >= 0: return NatMut(i) else: @@ -256,8 +619,9 @@ def times(self, f): + class Bool(Nat): - def try_new(b: bool): # -> Result[Nat] + def try_new(b: bool): # -> Result[Nat] if b == True or b == False: return Bool(b) else: @@ -268,81 +632,128 @@ def __str__(self) -> str: return "True" else: return "False" + def __repr__(self) -> str: return self.__str__() + def mutate(self): return BoolMut(self) + def invert(self): return Bool(not self) + class BoolMut(NatMut): value: Bool def __init__(self, b: Bool): self.value = b + def __repr__(self): return self.value.__repr__() + + def __bool__(self): + return bool(self.value) + + def __hash__(self): + return self.value.__hash__() + def __eq__(self, other): - if isinstance(other, bool): - return self.value == other - else: + if isinstance(other, MutType): return self.value == other.value - def __ne__(self, other): - if isinstance(other, bool): - return self.value != other else: + return self.value == other + + def __ne__(self, other): + if isinstance(other, MutType): return self.value != other.value + else: + return self.value != other + + def update(self, f): + self.value = Bool(f(self.value)) + def invert(self): self.value = self.value.invert() + class Str(str): def __instancecheck__(cls, obj): return isinstance(obj, str) - def try_new(s: str): # -> Result[Nat] + + def try_new(s: str): # -> Result[Nat] if isinstance(s, str): return Str(s) else: return Error("Str can't be other than str") + def get(self, i: int): if len(self) > i: return Str(self[i]) else: return None + def mutate(self): return StrMut(self) + def to_int(self): return Int(self) if self.isdigit() else None + def contains(self, s): return s in self + def __add__(self, other): return then__(str.__add__(self, other), Str) - def __radd__(self, other): - return then__(str.__add__(other, self), Str) + def __mul__(self, other): return then__(str.__mul__(self, other), Str) + def __mod__(self, other): return then__(str.__mod__(other, self), Str) -class StrMut(): # Inherits Str + def __getitem__(self, index_or_slice): + + if isinstance(index_or_slice, slice): + return Str(str.__getitem__(self, index_or_slice)) + elif isinstance(index_or_slice, Range): + return Str(str.__getitem__(self, index_or_slice.into_slice())) + else: + return str.__getitem__(self, index_or_slice) + + +class StrMut(MutType): # Inherits Str value: Str def __init__(self, s: str): self.value = s + def __repr__(self): return self.value.__repr__() + + def __str__(self): + return self.value.__str__() + + def __hash__(self): + return self.value.__hash__() + def __eq__(self, other): - if isinstance(other, Str): - return self.value == other - else: + if isinstance(other, MutType): return self.value == other.value - def __ne__(self, other): - if isinstance(other, Str): - return self.value != other else: + return self.value == other + + def __ne__(self, other): + if isinstance(other, MutType): return self.value != other.value + else: + return self.value != other + + def update(self, f): + self.value = Str(f(self.value)) + def try_new(s: str): if isinstance(s, str): self = StrMut() @@ -350,8 +761,10 @@ def try_new(s: str): return self else: return Error("Str! can't be other than str") + def clear(self): self.value = "" + def pop(self): if len(self.value) > 0: last = self.value[-1] @@ -359,376 +772,445 @@ def pop(self): return last else: return Error("Can't pop from empty `Str!`") + def push(self, s: str): self.value += s + def remove(self, idx: int): char = self.value[idx] - self.value = self.value[:idx] + self.value[idx+1:] + self.value = self.value[:idx] + self.value[idx + 1 :] return char + def insert(self, idx: int, s: str): self.value = self.value[:idx] + s + self.value[idx:] + class Float(float): - def try_new(i): # -> Result[Nat] + EPSILON = 2.220446049250313e-16 + + def try_new(i): # -> Result[Nat] if isinstance(i, float): - Float(i) + return Float(i) else: - Error("not a float") + return Error("not a float") + def mutate(self): return FloatMut(self) + + def __abs__(self): + return Float(float.__abs__(self)) + def __add__(self, other): return then__(float.__add__(self, other), Float) - def __radd__(self, other): - return then__(float.__add__(float(other), self), Float) + def __sub__(self, other): return then__(float.__sub__(self, other), Float) - def __rsub__(self, other): - return then__(float.__sub__(float(other), self), Float) + def __mul__(self, other): return then__(float.__mul__(self, other), Float) - def __rmul__(self, other): - return then__(float.__mul__(float(other), self), Float) + def __div__(self, other): return then__(float.__div__(self, other), Float) - def __rdiv__(self, other): - return then__(float.__div__(float(other), self), Float) + def __floordiv__(self, other): return then__(float.__floordiv__(self, other), Float) - def __rfloordiv__(self, other): - return then__(float.__floordiv__(float(other), self), Float) + + def __truediv__(self, other): + return then__(float.__truediv__(self, other), Float) + def __pow__(self, other): return then__(float.__pow__(self, other), Float) + def __rpow__(self, other): return then__(float.__pow__(float(other), self), Float) -class FloatMut(): # inherits Float + def __pos__(self): + return self + + def __neg__(self): + return then__(float.__neg__(self), Float) + + def nearly_eq(self, other, epsilon=EPSILON): + return abs(self - other) < epsilon + +class FloatMut(MutType): # inherits Float value: Float + EPSILON = 2.220446049250313e-16 + def __init__(self, i): self.value = Float(i) + def __repr__(self): return self.value.__repr__() + + def __hash__(self): + return self.value.__hash__() + def __deref__(self): return self.value + + def __float__(self): + return self.value.__float__() + def __eq__(self, other): - if isinstance(other, Float): - return self.value == other - else: + if isinstance(other, MutType): return self.value == other.value - def __ne__(self, other): - if isinstance(other, Float): - return self.value != other else: + return self.value == other + + def __ne__(self, other): + if isinstance(other, MutType): return self.value != other.value - def __le__(self, other): - if isinstance(other, Float): - return self.value <= other else: + return self.value != other + + def __le__(self, other): + if isinstance(other, MutType): return self.value <= other.value - def __ge__(self, other): - if isinstance(other, Float): - return self.value >= other else: + return self.value <= other + + def __ge__(self, other): + if isinstance(other, MutType): return self.value >= other.value - def __lt__(self, other): - if isinstance(other, Float): - return self.value < other else: + return self.value >= other + + def __lt__(self, other): + if isinstance(other, MutType): return self.value < other.value - def __gt__(self, other): - if isinstance(other, Float): - return self.value > other else: + return self.value < other + + def __gt__(self, other): + if isinstance(other, MutType): return self.value > other.value - def __add__(self, other): - if isinstance(other, Float): - return FloatMut(self.value + other) else: + return self.value > other + + def __add__(self, other): + if isinstance(other, MutType): return FloatMut(self.value + other.value) - def __sub__(self, other): - if isinstance(other, Float): - return FloatMut(self.value - other) else: + return FloatMut(self.value + other) + + def __sub__(self, other): + if isinstance(other, MutType): return FloatMut(self.value - other.value) - def __mul__(self, other): - if isinstance(other, Float): - return FloatMut(self.value * other) else: + return FloatMut(self.value - other) + + def __mul__(self, other): + if isinstance(other, MutType): return FloatMut(self.value * other.value) - def __floordiv__(self, other): - if isinstance(other, Float): - return FloatMut(self.value // other) else: + return FloatMut(self.value * other) + + def __floordiv__(self, other): + if isinstance(other, MutType): return FloatMut(self.value // other.value) - def __pow__(self, other): - if isinstance(other, Float): - return FloatMut(self.value ** other) else: - return FloatMut(self.value ** other.value) -class Array(list): - def dedup(self, f=None): - if f == None: - return Array(list(set(self))) + return FloatMut(self.value // other) + + def __truediv__(self, other): + if isinstance(other, MutType): + return FloatMut(self.value / other.value) else: - return Array(list(set(map(f, self)))) - def push(self, value): - self.append(value) - return self - def partition(self, f): - return Array(list(filter(f, self))), Array(list(filter(lambda x: not f(x), self))) -os__ = __import__("os.path") -os__ = __import__("os.path") + return FloatMut(self.value / other) + def __pow__(self, other): + if isinstance(other, MutType): + return FloatMut(self.value**other.value) + else: + return FloatMut(self.value**other) + def __pos__(self): + return self + def __neg__(self): + return FloatMut(-self.value) + def update(self, f): + self.value = Float(f(self.value)) -def int__(i): - try: - return Int(i) - except: - return None + def inc(self, value=1.0): + self.value = Float(self.value + value) -def nat__(i): - try: - return Nat(i) - except: - return None + def dec(self, value=1.0): + self.value = Float(self.value - value) -def float__(f): - try: - return Float(f) - except: - return None -def str__(s): - try: - return Str(s) - except: - return None -def if_tmp_func_3__(): - if (answer__ == Str("y")): - (print)(((Str("removing ") + (str__)(erg_dir__,)) + Str(" ...")),) - if_tmp_2__ = (su__).rmtree(erg_dir__,) - else: - (print)(Str("aborting installation"),) - if_tmp_2__ = (exit)(Nat(1),) - return if_tmp_2__ -def if_tmp_func_1__(): - if ( -(os__).path -).exists(erg_dir__,): - (print)(Str(".erg directory already exists, do you want to overwrite it? [y/n]"),end=Str(" "),) - global answer__ - answer__ = (input)() - if_tmp_0__ = if_tmp_func_3__() - else: - if_tmp_0__ = None - return if_tmp_0__ -urllib__ = __import__("urllib.request") -# from typing import TypeVar, Union, _SpecialForm, _type_check -class Error: - def __init__(self, message): - self.message = message -# T = TypeVar("T") -# @_SpecialForm -def Result(self, parameters): - """Result type. - Result[T] is equivalent to Union[T, Error]. - """ - # arg = _type_check(parameters, f"{self} requires a single type.") - return [arg, Error] -def is_ok(obj) -> bool: - return not isinstance(obj, Error) -# from collections.abc import Iterable, Sequence, Iterator, Container +class Array(list): + @staticmethod + def try_new(arr): # -> Result[Array] + if isinstance(arr, list): + return Array(arr) + else: + return Error("not a list") -class Range: - def __init__(self, start, end): - self.start = start - self.end = end - def __contains__(self, item): - pass - def __getitem__(self, item): - res = self.start + item - if res in self: - return res + def generic_try_new(arr, cls = None): # -> Result[Array] + if cls is None: + return Array.try_new(arr) else: - raise IndexError("Index out of range") - # TODO: for Str, etc. - def __len__(self): - if self.start in self: - if self.end in self: - # len(1..4) == 4 - return self.end - self.start + 1 - else: - # len(1..<4) == 3 - return self.end - self.start + elem_t = cls.__args__[0] + elems = [] + for elem in arr: + if not hasattr(elem_t, "try_new"): + return Error("not a " + str(elem_t)) + # TODO: nested check + elem = elem_t.try_new(elem) + if is_ok(elem): + elems.append(elem) + else: + return Error("not a " + str(elem_t)) + return Array(elems) + + def dedup(self, same_bucket=None): + if same_bucket is None: + return Array(list(set(self))) else: - if self.end in self: - # len(1<..4) == 3 - return self.end - self.start - else: - # len(1<..<4) == 2 - return self.end - self.start - 2 - def __iter__(self): - return RangeIterator(rng=self) + removes = [] + for lhs, rhs in zip(self, self[1:]): + if same_bucket(lhs, rhs): + removes.append(lhs) + for remove in removes: + self.remove(remove) + return self -# Sequence.register(Range) -# Container.register(Range) -# Iterable.register(Range) + def get(self, index, default=None): + try: + return self[index] + except IndexError: + return default -# represents `start<..end` -class LeftOpenRange(Range): - def __contains__(self, item): - return self.start < item <= self.end + def push(self, value): + self.append(value) + return self -# represents `start.. bool: + if isinstance(t, list): + if len(t) < len(self): + return False + for (inner_t, elem) in zip(t, self): + if not contains_operator(inner_t, elem): + return False + return True + elif isinstance(t, set): + return self in t + elif isinstance(t, UnionType): + return any([self.type_check(_t) for _t in t.__args__]) + elif not hasattr(t, "__args__"): + return isinstance(self, t) + elem_t = t.__args__[0] + l = None if len(t.__args__) != 2 else t.__args__[1] + if l is not None and l != len(self): + return False + for elem in self: + if not contains_operator(elem_t, elem): + return False + return True + + def update_nth(self, index, f): + self[index] = f(self[index]) + + def sum(self, start=0): + return sum(self, start) + + def prod(self, start=1): + from functools import reduce + return reduce(lambda x, y: x * y, self, start) + + def reversed(self): + return Array(list.__reversed__(self)) + + def insert_at(self, index, value): + self.insert(index, value) + return self - def __iter__(self): + def remove_at(self, index): + del self[index] return self - def __next__(self): - if issubclass(Nat, type(self.rng.start)): - if self.needle in self.rng: - result = self.needle - self.needle += 1 - return result - elif issubclass(Str, type(self.rng.start)): - if self.needle in self.rng: - result = self.needle - self.needle = chr(ord(self.needle) + 1) - return result - else: - if self.needle in self.rng: - result = self.needle - self.needle = self.needle.succ() - return result - raise StopIteration + def remove_all(self, item): + while item in self: + self.remove(item) + return self -# Iterator.register(RangeIterator) + def repeat(self, n): + from copy import deepcopy + new = [] + for _ in range(n): + new.extend(deepcopy(self)) + return Array(new) +class UnsizedArray: + elem: object + def __init__(self, elem): + self.elem = elem +os_L6 = __import__("os.path") +os_L6 = __import__("os.path") -def in_operator(x, y): - if type(y) == type: - if isinstance(x, y): - return True - elif is_ok(y.try_new(x)): - return True - # TODO: trait check - return False - elif (issubclass(type(y), list) or issubclass(type(y), set)) \ - and (type(y[0]) == type or issubclass(type(y[0]), Range)): - # FIXME: - type_check = in_operator(x[0], y[0]) - len_check = len(x) == len(y) - return type_check and len_check - elif issubclass(type(y), dict) and issubclass(type(next(iter(y.keys()))), type): - # TODO: - type_check = True # in_operator(x[next(iter(x.keys()))], next(iter(y.keys()))) - len_check = len(x) >= len(y) - return type_check and len_check + + + + +def int__(i): + return Int(i) + + +def nat__(i): + return Nat(i) + + +def float__(f): + return Float(f) + + +def str__(s): + return Str(s) +def if_tmp_func_3__(): + if (answer_L18_C4 == Str("y")): + (print)(((Str("Removing ") + (str__)(erg_dir_L12,)) + Str(" ...")),) + if_tmp_2__ = (su_L8).rmtree(erg_dir_L12,) + else: + (print)(Str("Aborting installation"),) + if_tmp_2__ = (exit)(Nat(1),) + return if_tmp_2__ +def if_tmp_func_1__(): + if ( +(os_L6).path +).exists(erg_dir_L12,): + (print)(Str(".erg directory already exists, do you want to overwrite it? [y/n]"),end=Str(" "),) + global answer_L18_C4 + answer_L18_C4 = (input)() + if_tmp_0__ = if_tmp_func_3__() else: - return x in y + if_tmp_0__ = None + return if_tmp_0__ +urllib_L1 = __import__("urllib.request") def match_tmp_func_5__(): - match (sys__).platform: - case "darwin": + match (sys_L5).platform: + case ("darwin") as __percent__p_desugar_1_L40_C4: match_tmp_4__ = Str("erg-x86_64-apple-darwin.tar.gz") - case "win32": + case ("win32") as __percent__p_desugar_2_L41_C4: match_tmp_4__ = Str("erg-x86_64-pc-windows-msvc.zip") case _: match_tmp_4__ = Str("erg-x86_64-unknown-linux-gnu.tar.gz") return match_tmp_4__ -urllib__ = __import__("urllib.request") +urllib_L1 = __import__("urllib.request") def if_tmp_func_7__(): - if ((sys__).platform == Str("win32")): - (print)(((Str("extracting ") + (str__)(filename__,)) + Str(" ...")),) - global bytesio__ - bytesio__ = (io__).BytesIO((stream__).read(),) - global zipfile__ - zipfile__ = (zf__).ZipFile(bytesio__,) - (zipfile__).extractall(erg_tmp_dir__,) - (zipfile__).close() - (su__).move(((Str("") + (str__)(erg_tmp_dir__,)) + Str("/erg.exe")),((Str("") + (str__)(erg_bin_dir__,)) + Str("/erg.exe")),) - (su__).move(((Str("") + (str__)(erg_tmp_dir__,)) + Str("/lib")),((Str("") + (str__)(erg_dir__,)) + Str("/lib")),) - if_tmp_6__ = (su__).rmtree(erg_tmp_dir__,) + if ((sys_L5).platform == Str("win32")): + (print)(((Str("Extracting ") + (str__)(filename_L39,)) + Str(" ...")),) + global bytesio_L51_C8 + bytesio_L51_C8 = (io_L7).BytesIO((stream_L47).read(),) + global zipfile_L52_C8 + zipfile_L52_C8 = (zf_L3).ZipFile(bytesio_L51_C8,) + (zipfile_L52_C8).extractall(erg_tmp_dir_L14,) + (zipfile_L52_C8).close() + (discard__)((su_L8).move(((Str("") + (str__)(erg_tmp_dir_L14,)) + Str("/erg.exe")),((Str("") + (str__)(erg_bin_dir_L13,)) + Str("/erg.exe")),),) + (discard__)((su_L8).move(((Str("") + (str__)(erg_tmp_dir_L14,)) + Str("/lib")),((Str("") + (str__)(erg_dir_L12,)) + Str("/lib")),),) + if_tmp_6__ = (su_L8).rmtree(erg_tmp_dir_L14,) else: - (print)(((Str("extracting ") + (str__)(filename__,)) + Str(" ...")),) - global tarfile__ - tarfile__ = (tf__).open(fileobj=stream__,mode=Str("r|gz"),) - (tarfile__).extractall(erg_tmp_dir__,) - (tarfile__).close() - (su__).move(((Str("") + (str__)(erg_tmp_dir__,)) + Str("/erg")),((Str("") + (str__)(erg_bin_dir__,)) + Str("/erg")),) - (su__).move(((Str("") + (str__)(erg_tmp_dir__,)) + Str("/lib")),((Str("") + (str__)(erg_dir__,)) + Str("/lib")),) - if_tmp_6__ = (su__).rmtree(erg_tmp_dir__,) + (print)(((Str("Extracting ") + (str__)(filename_L39,)) + Str(" ...")),) + global tarfile_L60_C8 + tarfile_L60_C8 = (tf_L2).open(fileobj=stream_L47,mode=Str("r|gz"),) + (tarfile_L60_C8).extractall(erg_tmp_dir_L14,) + (tarfile_L60_C8).close() + (discard__)((su_L8).move(((Str("") + (str__)(erg_tmp_dir_L14,)) + Str("/erg")),((Str("") + (str__)(erg_bin_dir_L13,)) + Str("/erg")),),) + (discard__)((su_L8).move(((Str("") + (str__)(erg_tmp_dir_L14,)) + Str("/lib")),((Str("") + (str__)(erg_dir_L12,)) + Str("/lib")),),) + if_tmp_6__ = (su_L8).rmtree(erg_tmp_dir_L14,) return if_tmp_6__ -urllib__ = (__import__)(Str("urllib"),) -tf__ = (__import__)(Str("tarfile"),) -zf__ = (__import__)(Str("zipfile"),) -json__ = (__import__)(Str("json"),) -sys__ = (__import__)(Str("sys"),) -os__ = (__import__)(Str("os"),) -io__ = (__import__)(Str("io"),) -su__ = (__import__)(Str("shutil"),) -homedir__ = ( -(os__).path +os_L6 = __import__("os.path") +def if_tmp_func_9__(): + if ((res2_L79).returncode != Nat(0)): + assert contains_operator(Bytes,(res2_L79).stderr) + if_tmp_8__ = (quit)(((Str("Failed to install poise: ") + (str__)(((res2_L79).stderr).decode(),)) + Str("")),) + else: + if_tmp_8__ = None + return if_tmp_8__ +urllib_L1 = (__import__)(Str("urllib"),) +tf_L2 = (__import__)(Str("tarfile"),) +zf_L3 = (__import__)(Str("zipfile"),) +json_L4 = (__import__)(Str("json"),) +sys_L5 = (__import__)(Str("sys"),) +os_L6 = (__import__)(Str("os"),) +io_L7 = (__import__)(Str("io"),) +su_L8 = (__import__)(Str("shutil"),) +sub_L9 = (__import__)(Str("subprocess"),) +homedir_L11 = ( +(os_L6).path ).expanduser(Str("~"),) -erg_dir__ = (homedir__ + Str("/.erg")) -erg_bin_dir__ = (homedir__ + Str("/.erg/bin")) -erg_tmp_dir__ = (homedir__ + Str("/.erg/tmp")) +erg_dir_L12 = (homedir_L11 + Str("/.erg")) +erg_bin_dir_L13 = (homedir_L11 + Str("/.erg/bin")) +erg_tmp_dir_L14 = (homedir_L11 + Str("/.erg/tmp")) if_tmp_func_1__() -(os__).mkdir(erg_dir__,) -(os__).mkdir(erg_bin_dir__,) -latest_url__ = Str("https://api.github.com/repos/erg-lang/erg/releases/latest") -_stream__ = ( -(urllib__).request -).urlopen(latest_url__,) -s__ = ((_stream__).read()).decode() -jdata__ = (json__).loads(s__,) -assert in_operator(jdata__,{(Str): (Str),}) -latest_version__ = (jdata__).__getitem__(Str("tag_name"),) -(print)(((Str("version: ") + (str__)(latest_version__,)) + Str("")),) -filename__ = match_tmp_func_5__() -url__ = ((((Str("https://github.com/erg-lang/erg/releases/download/") + (str__)(latest_version__,)) + Str("/")) + (str__)(filename__,)) + Str("")) -(print)(((Str("downloading ") + (str__)(url__,)) + Str(" ...")),) -stream__ = ( -(urllib__).request -).urlopen(url__,) +(os_L6).mkdir(erg_dir_L12,) +(os_L6).mkdir(erg_bin_dir_L13,) +latest_url_L30 = Str("https://api.github.com/repos/erg-lang/erg/releases/latest") +_stream_L31 = ( +(urllib_L1).request +).urlopen(latest_url_L30,) +s_L32 = ((_stream_L31).read()).decode() +jdata_L33 = (json_L4).loads(s_L32,) +assert contains_operator({(Str): (object),},jdata_L33) +latest_version_L35 = (jdata_L33).__getitem__(Str("tag_name"),) +(print)(((Str("version: ") + (str__)(latest_version_L35,)) + Str("")),) +filename_L39 = match_tmp_func_5__() +url_L43 = ((((Str("https://github.com/erg-lang/erg/releases/download/") + (str__)(latest_version_L35,)) + Str("/")) + (str__)(filename_L39,)) + Str("")) +(print)(((Str("Downloading ") + (str__)(url_L43,)) + Str(" ...")),) +stream_L47 = ( +(urllib_L1).request +).urlopen(url_L43,) if_tmp_func_7__() -(print)(((((Str("please add `.erg` to your PATH by running `export PATH=$PATH:") + (str__)(erg_bin_dir__,)) + Str("` and `export ERG_PATH=")) + (str__)(erg_dir__,)) + Str("`")),) +(print)(Str("erg installed successfully"),) +poise_git_url_L69 = Str("https://github.com/erg-lang/poise.git") +(print)(Str("Cloning poise (erg package manager) ..."),) +(os_L6).mkdir(erg_tmp_dir_L14,) if (not (( +(os_L6).path +).exists(erg_tmp_dir_L14,))) else None +(os_L6).chdir(erg_tmp_dir_L14,) +res_L74 = (sub_L9).run(Array([Str("git"),Str("clone"),poise_git_url_L69,]),capture_output=Bool(True),) +(quit)(Str("Failed to clone poise repo"),) if ((res_L74).returncode != Nat(0)) else None +(os_L6).chdir(Str("poise"),) +(print)(Str("Building poise ..."),) +res2_L79 = (sub_L9).run(Array([Str("erg"),Str("src/main.er"),Str("--"),Str("install"),]),capture_output=Bool(True),) +if_tmp_func_9__() +(print)(Str("poise installed successfully"),) +(os_L6).chdir(Str(".."),) +(su_L8).rmtree(Str("poise"),) +(print)(((((Str("Please add `.erg` to your PATH by running `export PATH=$PATH:") + (str__)(erg_bin_dir_L13,)) + Str("` and `export ERG_PATH=")) + (str__)(erg_dir_L12,)) + Str("`")),)