Ejemplo n.º 1
0
def _equals(inter: InterpretContext, equal_loc: CodeLocation) -> None:
    orig_loc = copy.deepcopy(inter.next_tok.loc)
    if inter.anon_tok or inter.call_tok:
        # prevent assignment to anonymous tokens.
        raise NotImplementedError
    if inter.dec.type_:
        assignee = None
    else:
        assignee = inter.curr_tok.thing

    inter.advance_tokens()
    inter.equaling = True
    value = _expression_dispatch(inter)
    inter.equaling = False
    if not value:
        if inter.named_statement:
            # Prevent assignment of non-anonymous statements.
            # Class anonName = class RealName {||}
            raise d_SyntaxError(
                "A named declaration cannot be used for assignment", orig_loc)
        else:
            raise d_CriticalError(
                "No value for _expression_dispatch in _equals")
    if assignee:
        assignee.set_value(value)
    else:
        try:
            _add_attr_wrap(inter, value=value)
        except d_TypeMismatchError as err:
            err.loc = equal_loc
            raise
Ejemplo n.º 2
0
def _check_for_duplicates(thing: d_Container, name: str) -> None:
    if isinstance(thing, d_Inst):
        var = thing.compose_prefix(name)
    else:
        var = d_Variable(name)
    if var in thing.attrs:
        raise d_CriticalError(f"A duplicate attribute was found: '{name}'")
Ejemplo n.º 3
0
    def add_attr(self,
                 dec: Declarable,
                 value: Optional[d_Thing] = None,
                 use_ref: bool = False) -> d_Thing:
        ref = None
        if dec.name is None:
            raise d_CriticalError("A declarable had no name")

        _check_for_duplicates(self, dec.name)

        if value:
            res = check_value(value, dec)
            if res:
                raise d_TypeMismatchError(
                    f"Cannot assign {res.actual} to {res.expected}{res.extra}")

            if dec.type_ == d_Grammar.PRIMITIVE_THING:
                value.can_be_anything = True
            if use_ref:
                # Use a ref to hide the original name without changing it
                # Currently only used for function parameters afaik
                ref = d_Ref(dec.name, value)
            else:
                value.name = dec.name
        else:
            value = _type_to_obj(dec)

        fin_val = ref or value
        fin_var = d_Variable(fin_val.name)
        if isinstance(self, d_Inst):
            fin_var = self.compose_prefix(fin_val.name)

        self.attrs[fin_var] = fin_val
        return value
Ejemplo n.º 4
0
 def set_value(self, new_value: d_Thing) -> None:
     self.is_null = new_value.is_null
     if isinstance(new_value, d_List):
         # listOf Str = ['1', '2'];
         self.list_ = new_value.list_
         _check_list_type(self)
     elif self.can_be_anything:
         super().set_value(new_value)
     elif isinstance(new_value, d_Thing):  # type: ignore
         raise d_TypeMismatchError(
             f"Cannot assign {new_value.public_type} to List")
     else:
         raise d_CriticalError("Unrecognized type for list assignment")
Ejemplo n.º 5
0
def _type_to_obj(dec: Declarable) -> d_Thing:
    thing: d_Thing = None  # type: ignore
    if not dec.type_:
        raise d_CriticalError("A declarable had no type")
    elif isinstance(dec.type_, d_Class):
        thing = d_Inst()
        thing.parent = dec.type_
    elif dec.listof:
        thing = d_List()
        # this prim_to_value might fail with classes
        thing.contained_type = prim_to_value(dec.type_)  # type: ignore
    elif dec.type_ == d_Grammar.PRIMITIVE_THING:
        thing = d_Thing()
        thing.can_be_anything = True
    else:
        # equivalent to thing = d_Str(), just with the Object Dispatch
        thing = OBJECT_DISPATCH[dec.type_]()

    if thing:
        thing.name = dec.name
        return thing
    else:
        raise d_CriticalError("Unrecognized type for declaration")
Ejemplo n.º 6
0
    def set_value(self, new_value: d_Thing) -> None:
        # alter own class to *become* the type it is assigned to.
        # note that 'can_be_anything' is still True
        # and public_type is still "Thing"
        if isinstance(new_value, d_Thing):  # type: ignore
            self.__class__ = new_value.__class__
            self.grammar = new_value.grammar
            self.public_type = new_value.public_type
        else:
            raise d_CriticalError("Unrecognized type for thing assignment")

        if not type(new_value) == d_Thing:
            # After altering class, set the actual value using subclass set_value
            self.set_value(new_value)
Ejemplo n.º 7
0
def _generate_origin(err: d_DitError,
                     inter: InterpretContext,
                     loc: Optional[CodeLocation] = None) -> None:
    if not err.loc:
        # If the code is total garbage, the next token may not be assigned.
        # In that case, we default to wherever the char_feed happens to be.
        if inter.next_tok:
            err.loc = inter.next_tok.loc
        else:
            err.loc = inter.char_feed.loc

    if inter.body.path is None:
        raise d_CriticalError("A body had no path during exception")
    code = inter.char_feed.get_line(err.loc)
    err.set_origin(inter.body.path, code)
Ejemplo n.º 8
0
 def find_attr(self,
               name: str,
               scope_mode: bool = False) -> Optional[d_Thing]:
     var = d_Variable(name)
     if isinstance(self, d_Inst):
         var = self.compose_prefix(name)
     if scope_mode:
         if not isinstance(self, d_Body):
             raise d_CriticalError("A Container was given for scope mode")
         # We need to check for this name in upper scopes
         # Str someGlobal = 'cat';
         # class someClass {| Str someInternal = someGlobal; |}
         return _find_attr_in_scope(var, self)
     else:
         # We're dotting, so only 'self' counts, no upper scopes.
         # We also need to check for inherited parent classes
         # someInst.someMember = ...
         return _find_attr_in_self(var, self)
Ejemplo n.º 9
0
def _paren_left(inter: InterpretContext) -> Optional[d_Thing]:
    func = (inter.anon_tok or inter.call_tok or inter.curr_tok).thing
    if isinstance(func, d_Class):
        # This means we must be instantiating, and need the Make func
        # Number num = Number('3');
        func = _make(inter)
    elif not isinstance(func, d_Func):
        raise d_CriticalError(f"Expected function, got {func.public_type}")

    func.new_call()  # handles recursive attribute stack

    stored_inst = None
    if inter.dotted_inst and not inter.equaling:
        # We are activating a function of this instance, so the func needs 'this'
        # Subject to change when static functions are implemented
        # num.inc();
        func.add_attr(
            Declarable(inter.dotted_inst.parent, THIS),
            inter.dotted_inst,
            use_ref=True,
        )
        stored_inst = inter.dotted_inst
    inter.dotted_inst = None  # type: ignore

    _get_func_args(inter, func)

    if not func.code and func.lang is not b_Ditlang:
        preprocess(func)

    inter.call_tok = _run_func(inter, func)

    func.end_call()

    if stored_inst:
        stored_inst.pop_func_sep()

    if inter.call_tok.grammar == d_Grammar.NULL:
        return _terminal(inter)
    else:
        return _parenable(inter)
Ejemplo n.º 10
0
def _dot(inter: InterpretContext) -> Token:
    inter.advance_tokens(False)  # We want to manage the next word ourselves
    if inter.next_tok.grammar != d_Grammar.WORD:
        raise d_SyntaxError(f"'{inter.next_tok.grammar}' is not dotable")

    # Allows dotting of anonymous tokens and function calls.
    target = (inter.anon_tok or inter.call_tok or inter.prev_tok).thing

    if isinstance(target, d_Inst):
        # We need to prepare in case the instance has inherited parents
        target.clear_prefix_to_func()
        inter.dotted_inst = target
    elif not isinstance(target, d_Container):
        raise d_CriticalError(f"Expected container, got {target.public_type}")

    result = target.find_attr(inter.next_tok.word)
    if not result and inter.dotted_inst:
        # this.B.attribute
        # We are doing explicit name disambiguation, looking in parent B instead of A.
        # B obviously doesn't have the attribute, the instance does.
        # So we look again in the instance.
        result = inter.dotted_inst.find_attr(inter.next_tok.word)

    if result:
        # The dot had a known variable, which we just need to return
        if isinstance(result, d_Func) and inter.dotted_inst:
            # this.func()
            # if `func` is an inherited function, we need to remember that we
            # called it so the prefixes are set up correctly.
            inter.dotted_inst.add_func_sep()
        return Token(result.grammar,
                     copy.deepcopy(inter.next_tok.loc),
                     thing=result)
    else:
        # The name was not found in the dotted body, so its a new name.
        # This means we are declaring a new var in the dotted body.
        # AKA Monkey patching
        inter.next_tok.grammar = d_Grammar.NEW_NAME
        inter.dotted_body = target  # Save for assignment
        return inter.next_tok
Ejemplo n.º 11
0
    def handle_filepath(self) -> None:
        if self.view is not None:
            return
        if self.path is None:
            raise d_CriticalError("A dit had no path")
        if self.path.startswith("https://") or self.path.startswith("http://"):
            try:
                contents = urlopen(self.path).read().decode()
            except (HTTPError, URLError) as error:
                raise d_FileError(f"Import failed, {error}")
        else:
            try:
                with open(self.path) as file_object:
                    contents = file_object.read()
            except FileNotFoundError:
                raise d_FileError("Import failed, file not found")
            except PermissionError:
                raise d_FileError("Import failed, permission denied")
            except IsADirectoryError:
                raise d_FileError("Import failed, not a directory")

        self.view = memoryview(contents.encode())
Ejemplo n.º 12
0
def _service_client(key: selectors.SelectorKey, mask: int):
    """Send or receive message from a guest lang."""
    global JOB
    conn: socket.socket = key.fileobj  # type: ignore
    client = _get_client(key.data)
    if client is None:
        return
    if JOB and mask & selectors.EVENT_READ:
        recv_data = conn.recv(1024)
        if recv_data:
            data = _decode(recv_data)
            if data["type"] == JobType.HEART.value:
                pass
            elif data["type"] == JobType.CRASH.value:
                JOB.crash = d_CodeError(data["result"], JOB.func.lang.name,
                                        JOB.func.guest_func_path)
            elif data["type"] == JobType.EXE_DITLANG.value:
                JOB.result = data["result"]
                JOB.type_ = JobType.EXE_DITLANG
            elif data["type"] == JobType.FINISH_FUNC.value:
                JOB.type_ = JobType.FINISH_FUNC
                JOB.active = False
            else:
                raise d_CriticalError("Unrecognized job type")

    elif mask & selectors.EVENT_WRITE:
        if (JOB and not JOB.active and JOB.func.lang == client.lang
                and JOB.type_ in (
                    JobType.CALL_FUNC,
                    JobType.DITLANG_CALLBACK,
                    JobType.RETURN_KEYWORD,
                    JobType.CLOSE,
                )):
            global PORT
            mes = JOB.get_json()
            conn.sendall(mes)
            JOB.active = True
Ejemplo n.º 13
0
def _trigger_eof_err(inter: InterpretContext) -> NoReturn:
    inter.char_feed.pop()
    raise d_CriticalError("EOF reached, but failed to trigger")
Ejemplo n.º 14
0
 def is_ready(self) -> bool:
     if self.view is None:
         raise d_CriticalError("A body had no view during readying")
     return len(self.view) > 0
Ejemplo n.º 15
0
 def get_data(self) -> None:
     if self.is_null:
         return None
     else:
         raise d_CriticalError("Thing get_data called on non-null thing.")
Ejemplo n.º 16
0
 def __str__(self):
     if self.is_null:
         return d_Grammar.NULL.value
     else:
         raise d_CriticalError("Thing __str__ called on non-null thing.")