def test_tail_call_in_conditional_then(self) -> None:
     prog = sexp.parse(
         '(define (vacuous-tail) (if true (vacuous-tail) false))')
     self.finder.visit(prog)
     self.assertEqual(1, len(self.finder.tail_calls))
     self.assert_symbol_in_tail_calls(sexp.SSym('vacuous-tail'),
                                      self.finder.tail_calls)
 def test_tail_call_in_one_branch_linear_call_in_other(self) -> None:
     prog = sexp.parse('''
         (define (vacuous-tail)
             (if true (+ 1 (vacuous-tail)) (vacuous-tail))
         )''')
     self.finder.visit(prog)
     self.assertEqual(1, len(self.finder.tail_calls))
     self.assert_symbol_in_tail_calls(sexp.SSym('vacuous-tail'),
                                      self.finder.tail_calls)
Exemple #3
0
    def _is_true_assertion(self, call: sexp.SCall) -> bool:
        if self._expr_types is None:
            return False

        if call.func != sexp.SSym('assert') or len(call.args) != 1:
            return False

        call_arg = call.args[0]
        if not self._expr_types.expr_value_known(call_arg):
            return False

        return self._expr_types.get_expr_value(call_arg) == sexp.SBool(True)
Exemple #4
0
    def _get_replacement_vector_index_func(
            self, call: sexp.SCall) -> Optional[sexp.SSym]:
        if self._expr_types is None:
            return None

        if not isinstance(call.func, sexp.SSym):
            return None

        if call.func not in (sexp.SSym('vector-index'),
                             sexp.SSym('vector-set!')):
            return None

        if len(call.args) < 2:
            return None

        if not self._expr_types.expr_type_known(call.args[0]):
            return None

        vec_arg_type = self._expr_types.get_expr_type(call.args[0])
        if not isinstance(vec_arg_type, scheme_types.SchemeVectType):
            return None

        if vec_arg_type.length is None:
            return None

        index_arg = call.args[1]
        if not self._expr_types.expr_value_known(index_arg):
            return None

        index = self._expr_types.get_expr_value(index_arg)
        if not isinstance(index, sexp.SNum):
            return None

        in_bounds = index.value >= 0 and index.value < vec_arg_type.length
        if not in_bounds:
            return None

        return (sexp.SSym('inst/load')
                if call.func == sexp.SSym('vector-index')
                else sexp.SSym('inst/store'))
Exemple #5
0
    def _add_is_function_check(
            self, function_expr: bytecode.Parameter,
            add_to_block: bytecode.BasicBlock) -> None:
        typeof_var = bytecode.Var(next(self.var_names))
        typeof_instr = bytecode.TypeofInst(
            typeof_var, function_expr)
        is_function_var = bytecode.Var(next(self.var_names))
        is_function_instr = bytecode.BinopInst(
            is_function_var, bytecode.Binop.SYM_EQ,
            typeof_var, bytecode.SymLit(sexp.SSym('function'))
        )
        branch_instr = bytecode.BrnInst(is_function_var, IS_FUNCTION_TRAP)

        for instr in [typeof_instr, is_function_instr, branch_instr]:
            add_to_block.add_inst(instr)
    def test_fib_tail(self) -> None:
        prog = sexp.parse('''
            (define (fib-tail n)
                (fib-tail-impl n 0 1)
            )

            (define (fib-tail-impl n first second)
                (if (= n 0)
                    first
                    (if (= n 1)
                        second
                        (fib-tail-impl (- n 1) second (+ first second))
                    )
                )
            )''')

        self.finder.visit(prog)
        self.assertEqual(1, len(self.finder.tail_calls))
        self.assert_symbol_in_tail_calls(sexp.SSym('fib-tail-impl'),
                                         self.finder.tail_calls)
 def test_basic_tail_call(self) -> None:
     prog = sexp.parse('(define (vacuous-tail) (vacuous-tail))')
     self.finder.visit(prog)
     self.assertEqual(1, len(self.finder.tail_calls))
     self.assert_symbol_in_tail_calls(sexp.SSym('vacuous-tail'),
                                      self.finder.tail_calls)
Exemple #8
0
 def type_name(self) -> sexp.SSym:
     return sexp.SSym('symbol')
Exemple #9
0
 def type_name(self) -> sexp.SSym:
     return sexp.SSym('number')
Exemple #10
0
 def decorator(cls: Type[BuiltinCallTypeEvaler]
               ) -> Type[BuiltinCallTypeEvaler]:
     _builtin_const_exprs[sexp.SSym(func_name)] = cls
     return cls
Exemple #11
0
 def type_name(self) -> sexp.SSym:
     return sexp.SSym('function')
Exemple #12
0
 def type_name(self) -> sexp.SSym:
     return sexp.SSym('vector')
Exemple #13
0
        else_type = self.get_expr_type(cond.else_expr)

        if (self.get_expr_type(cond.test) == SchemeBool
                and self.expr_value_known(cond.test)):
            expr_val = self.get_expr_value(cond.test)
            assert isinstance(expr_val, sexp.SBool)
            if expr_val.value:
                self.set_expr_type(cond, then_type)
            else:
                self.set_expr_type(cond, else_type)
        else:
            self.set_expr_type(cond, then_type.join_with(else_type))


_BUILTINS_FUNC_TYPES: Dict[sexp.SSym, SchemeObjectType] = {
    sexp.SSym('inst/typeof'):  SchemeFunctionType(1, SchemeSym),
    sexp.SSym('inst/trap'): SchemeFunctionType(0, SchemeBottom),
    sexp.SSym('inst/trace'): SchemeFunctionType(1, SchemeNum),
    sexp.SSym('inst/display'): SchemeFunctionType(1, SchemeNum),
    sexp.SSym('inst/newline'): SchemeFunctionType(0, SchemeNum),
    sexp.SSym('inst/breakpoint'): SchemeFunctionType(0, SchemeNum),
    sexp.SSym('inst/alloc'): SchemeFunctionType(1, SchemeVectType(None)),
    sexp.SSym('inst/load'): SchemeFunctionType(2, SchemeObject),
    sexp.SSym('inst/store'): SchemeFunctionType(3, SchemeVectType(None)),
    sexp.SSym('inst/length'): SchemeFunctionType(1, SchemeNum),

    sexp.SSym('inst/+'): SchemeFunctionType(2, SchemeNum),
    sexp.SSym('inst/-'): SchemeFunctionType(2, SchemeNum),
    sexp.SSym('inst/*'): SchemeFunctionType(2, SchemeNum),
    sexp.SSym('inst//'): SchemeFunctionType(2, SchemeNum),
    sexp.SSym('inst/%'): SchemeFunctionType(2, SchemeNum),