~jasper/type_stack_calc

ref: 84f5ae07ac5b8dfc401bde572d7cdc95a5d2e5fe type_stack_calc/type_stack_calc/base/component.py -rw-r--r-- 5.4 KiB
84f5ae07 — Jasper den Ouden minor 8 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#  Copyright (C) 2021 Jasper den Ouden.
#
#  This is free software: you can redistribute it and/or modify
#  it under the terms of the Affero GNU General Public License as published
#  by the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.

from type_stack_calc.ib.simple_ib_fun import SimpleInbuildFunction
from type_stack_calc.base.n_args import BaseNArgs

from type_stack_calc.extractor import Extractor
from type_stack_calc.pe.drop import PostExtractDrop

from type_stack_calc.ib.plain_component import PlainComponent

from type_stack_calc.util.stack_check import assert_acceptable_vals

class BaseComponentSet(BaseNArgs):
    """Sets a variable."""
    with_vars, n = True, 2
    c_name, infix, fun_tp = '=', True, 'method'

    def __init__(self):
        self.initial_set, self.definitional = False, False

    def deal_relevant_comp(self, rl, args):
        args[0].relevant_comp = rl
        for c in rl.values():
            if getattr(c, 'affects_comp', None) is None:
                c.affects_comp = dict()
            c.affects_comp[id(args[0])] = args[0]

    def extract(self, extractor, gen, tp):
        """Only needs extraction if specifying type now. Though can be specified to always do it."""
        # TODO return for instance should _never_ need extraction?
        if self.initial_set or extractor.always_extract_set:
            # Extract a bit.
            ilist = []
            ext = Extractor((ilist.append, extractor[1]))
            extractor[1](self)  # Extract the set.
            ext.extract_1(gen)
            varlist = ilist.copy()  # Need the variable portion...
            ext.extract_1(gen)
            extractor[1](ilist + [PostExtractDrop])
            extractor[0](varlist)  # ... which goes into the arguments.
        else:  # Plainly set in side.
            self.extract_top(extractor, gen, tp)

    def to_c(self, tc, gen):
        wfile, prep = tc[:2]
        var = next(gen)
        if not isinstance(var, BaseComponent):
            var2 = next(gen)
            assert isinstance(var2, BaseComponent), f"Not a component {var} {var2} {self}"
            var = var2

        if var.key == '~r':  # NOTE there may be more of these.
            wfile("return ")
        else:
            if self.initial_set:
                #assert var.val is not None, var  # TODO
                wfile((var.val and var.val.c_name or f"Bug({var})") + " ")
            wfile(f"{var.key} = ")
        tc.new_context(prep, '(').c_1(gen)

    def tp_calc(self, sc, vs, args):
        to, c = args
        if isinstance(to, BaseComponent):  # no layered components.
            to = to.val
            assert not isinstance(to, BaseComponent)

        assert_acceptable_vals((to,), c, vs, desc='Setting variable')

        self.initial_set = c.sc_set(sc, to)
        self.definitional = getattr(to, 'definitional', None)
        assert id(c.access_obj.get_comp(c.key)) == id(c)
        #self.initial_set = c.access_obj.sc_set_param(sc, c, to)
        sc.does.add('something')  # Variables were modified.

        if not getattr(self, 'destructive', None):
            self.destructive = getattr(to, 'destructive', None) and 'setcomp'
        return [to], self

    def __repr__(self): return ".set"

class BaseComponent:
    """Handles (global)variables, members of access_objects.
NOTE: it doesn't access `.set`, `.glob` from the value because the methods for those are `with_vars`, so `deal_with_var` won't unpack the variables then."""

    def __init__(self, access_obj, key):
        self.val = None
        assert_acceptable_vals((access_obj,), key,
            desc="Making component object for {access_obj}, {key}")
        assert access_obj is not None, key
        self.access_obj, self.key = access_obj, key
        if key[0] == '~': self.destructive = 'returnlike'

    @property
    def param_set(self):  # Gotta be a new one each time.
        return self._param_set_cls()  # Note: breaks @property assumptions?
    param_ = param_set

    @property  # TODO remove?
    def tp_stack(self): return [self.val]

    def _param_glob(self):
        """Ask for global variable."""
        assert False, f"Only local variables can ask to become globals. {self} ({type(self)})"

    param_glob = SimpleInbuildFunction(1, _param_glob, with_vars=True,
                                       name='glob')

    def get_comp(self, key):
        """Gets a component. Looks in the variable before the value!"""
        if got := getattr(self, f"param_{key}", None):
            return PlainComponent(key, got)
        assert_acceptable_vals((self.val,), desc='Getting component value invalid')
        return self.val.get_comp(key)

    def __repr__(self):
        assert not isinstance(self.val, BaseComponent), (type(self), self.key)
        return f"{self._repr_kind}:{self.key}:{self.val}"

    @property
    def c_name(self): return self.key

    def to_c(self, tc, _gen):
        """Produce C code, if constant, it's used and the variable name commented out."""
        val = self.val
        assert val is not None, self
        const_c = val.is_const and getattr(val, 'c_name', None)
        tc[0](const_c + f"/*{self.key}*/" if const_c else self.key)

    def sc_set(self, _sc, _to):  # Placeholder.
        """Sets variable to a value. Will notify stuff of the name, and set/smoosh the type.
Not actually defined in BaseComponent, defined downstream."""
        assert False, f"BUG: probably sc_set not defined for {self}"