Esempio n. 1
0
def _find_digit(inter: InterpretContext) -> Optional[Token]:
    lok = copy.deepcopy(inter.char_feed.loc)
    cur = inter.char_feed.current()
    if DIGIT.match(cur):
        inter.char_feed.pop()
        # we only get the first digit, interpreter handles the number
        return Token(d_Grammar.DIGIT, lok, cur)
Esempio n. 2
0
def _run_func(inter: InterpretContext, func: d_Func) -> Token:
    try:
        if func.is_built_in:
            if func.name == "getConfig":
                _handle_get_config(inter, func)
            else:
                func.py_func(func)
        elif func.lang is b_Ditlang:
            interpret(func)
        else:
            if not func.code:
                raise ReturnController(d_Thing.get_null_thing(), func,
                                       func.call_loc)
            _job_loop(GuestDaemonJob(JobType.CALL_FUNC, func))

    except d_CodeError as err:
        err.loc = func.call_loc
        # err.set_origin(
        #    inter.body.path, func.call_loc, inter.char_feed.get_line(func.call_loc)
        # )
        raise err
    except d_DitError as err:
        err.add_trace(func.path, func.call_loc, func.name)
        raise err
    except ReturnController as ret:
        if func.lang is not b_Ditlang:
            job = GuestDaemonJob(JobType.RETURN_KEYWORD, func)
            run_job(job)
        return ret.token
    except d_TypeMismatchError as mis:
        raise NotImplementedError
    else:
        if func.return_ and func.return_ != d_Grammar.VOID:
            raise d_SyntaxError(f"{func.pub_name()} expected a return",
                                func.call_loc)
        elif func.name == MAKE:
            thing = func.find_attr(THIS)
            if not thing:
                raise NotImplementedError
            return Token(d_Grammar.VALUE_INST, func.call_loc, thing=thing)
        else:
            # func ended without 'return' keyword
            return Token(d_Grammar.NULL, func.call_loc)
Esempio n. 3
0
def _find_single_chars(inter: InterpretContext) -> Optional[Token]:
    cur = inter.char_feed.current()
    lok = copy.deepcopy(inter.char_feed.loc)
    for d_Grammar in SINGLES:
        if cur == d_Grammar.value:
            # WET, appears in _find_double_chars
            if inter.char_feed.eof():
                inter.eof = True
            else:
                inter.char_feed.pop()
            return Token(d_Grammar, lok)
    return None
Esempio n. 4
0
def _find_words(inter: InterpretContext, find_word: bool) -> Optional[Token]:
    token_loc = copy.deepcopy(inter.char_feed.loc)
    word = _get_word(inter)
    if word:
        # Keywords first
        for grammar in KEYWORDS:
            if word == grammar.value:
                return Token(grammar, token_loc)
        for built_in in BUILT_INS:
            if word == built_in.name:
                return Token(d_Grammar.VALUE_FUNC, token_loc, thing=built_in)
        # Used by var.class.attr expressions
        # They find the word themselves.
        if find_word is False:
            return Token(d_Grammar.WORD, token_loc, word=word)
        # Most names
        attr = inter.body.find_attr(word, scope_mode=True)
        if attr:
            return Token(attr.grammar, token_loc, thing=attr)
        else:
            return Token(d_Grammar.NEW_NAME, token_loc, word=word)
    else:
        return None
Esempio n. 5
0
def _find_double_chars(inter: InterpretContext) -> Optional[Token]:
    if inter.char_feed.eof():  # Can't be double if we only have 1 char
        return None

    cur = inter.char_feed.current() + inter.char_feed.peek()
    lok = copy.deepcopy(inter.char_feed.loc)
    for d_Grammar in DOUBLES:
        if cur == d_Grammar.value:
            inter.char_feed.pop()  # pop first char in double
            if inter.char_feed.eof():
                inter.eof = True
            else:
                inter.char_feed.pop()  # pop the second if it's safe
            return Token(d_Grammar, lok)
Esempio n. 6
0
def _handle_anon(
    inter: InterpretContext,
    anon_body: d_Body,
    orig_loc: CodeLocation,
    lang: Optional[d_Lang] = None,
) -> Optional[d_Body]:
    if anon_body.name:
        # traditional statement, stop here
        if lang and isinstance(anon_body, d_Lang):
            # a language is being redeclared, must call set_value to
            # activate priority comparison stuff
            lang.set_value(anon_body)
        else:
            inter.body.attrs[d_Variable(anon_body.name)] = anon_body
        inter.named_statement = True
        return None
    else:
        # anonymous expression, need to dispatch it
        inter.anon_tok = Token(anon_body.grammar, orig_loc, thing=anon_body)
        return _expression_dispatch(inter)  # type: ignore
Esempio n. 7
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
Esempio n. 8
0
def _handle_eof(inter: InterpretContext) -> Token:
    inter.eof = True
    return Token(d_Grammar.EOF, copy.deepcopy(inter.char_feed.loc))