@@ 13,14 13,17 @@ from type_stack_calc.sc_parser import parser
from type_stack_calc.ib.scope import scopify
+import type_stack_calc.intro.load as loader # TODO stupid-side-effects-based.
+
import sys
from subprocess import Popen, PIPE
import subprocess
-import pathlib
class Finished(BaseException): pass
class HighlightCmd(tuple):
+ """Generates a list for argv doing highlighting commands."""
+
def params(self, **params):
return [s.format_map(params) for s in self[1]]
@@ 28,14 31,15 @@ class HighlightCmd(tuple):
return subprocess.Popen(['which', self[1][0]]).wait() == 0
class Main(StackCalc):
+ """Class for main type stack calculation program."""
highlight_try = list(map(HighlightCmd,
[('bat', ['bat', '-f', '-pp', '-l', "{lang}"]),
('vimcat', ['vimcat', '-c', 'set', "filetype={lang}"]),
('cat', ['cat'])]))
- def __init__(self, want=None):
- StackCalc.__init__(self)
+ def __init__(self, want=None, paths=None):
+ StackCalc.__init__(self, paths=paths)
self.want = set(['highlight']) if want is None else want
self.highlight_with = next(filter(HighlightCmd.available,
self.highlight_try))
@@ 168,6 172,9 @@ class Main(StackCalc):
text=True, stdin=PIPE,
stdout=sys.stdout)
self._c_variants(proc.stdin, vs.items(), 0)
+ # TODO package names in C?
+ for load_vs in loader.loader.values():
+ self._c_variants(proc.stdin, load_vs.items(), 0)
proc.stdin.close()
proc.wait()
else:
@@ 0,0 1,42 @@
+"""Introduces the import function."""
+
+from pathlib import Path
+from type_stack_calc.sc_parser import parser
+
+from type_stack_calc.intro import intro
+from type_stack_calc.ib.scope import scopify
+def _ignore(_c1): pass
+
+class LoadCall(dict):
+ def __repr__(self): return f"LoadCall"
+
+ fun_tp, n = 'method', 1
+ c_name = 'LoadCall'
+
+ def load(self, sc, vs, path):
+ """Gets loaded from dictionary if available, otherwise looks in `sc.paths`, and runs again."""
+ got = self.get(path)
+ if got is None: # Don't have it yet.
+ for origin_path in sc.paths: # Try use the paths available.
+ p = Path(origin_path + path + ".tsc")
+ if p.exists():
+ new_vs = scopify(intro)
+ sc.tp_calc(parser(p.read_text()), new_vs, [], _ignore)
+ got = new_vs
+ break
+ assert got is not None, \
+ f"Could not find {path}, searched {sc.paths}"
+ self[path] = got
+ return got
+
+ def tp_calc(self, sc, vs, inp):
+ load_path = inp[0]
+ assert isinstance(load_path, str), \
+ f"Must be constant string right now, got {load_path}"
+ got = self.load(sc, vs, load_path)
+ return [got], got
+
+from type_stack_calc.tp.str import ConstStr
+
+loader = LoadCall()
+ConstStr.param_load = loader
@@ 37,32 37,37 @@ def interpret_word(word):
class StackCalc:
"""Calculates types, heart of the implementation, basically."""
- def __init__(self, origin=None):
- self.origin = origin
+ def __init__(self, origin=None, paths=None):
+ self.origin = origin # Note: component_collection does use it.
+ self.paths = [] if paths is None else paths
self.does = set()
def deal_with_var(self, var, code, vs, stack, into):
"""Gets variable, applies as function if relevant."""
val = var.val # For instance a function immediately called.
+
+ assert_acceptable_vals(stack, val)
# If it has a type function, run it.
- if tp_fun := val and getattr(val, 'tp_calc', None):
+ if tp_fun := getattr(val, 'tp_calc', None):
if val.fun_tp == 'plain':
stack = stack[:-1] # Ditch the origin.
# elif val.fun_tp == 'class_method':
# assert isinstance(stack[-1], Scope)
else:
- assert val.fun_tp == 'method'
+ assert val.fun_tp == 'method', \
+ "Only `plain` and `method` function types permitted. Got: {val.fun_tp}"
# Strip to number of arguments if `n` indicates that.
n = getattr(val, 'n', None)
- args, rest = (stack, []) if (n is None) else \
+ inp, rest = (stack, []) if (n is None) else \
(([], stack) if n==0 else (stack[-n:], stack[:-n]))
if n is not None:
- assert len(args) == n, (stack, n, stack[-n:], args)
+ assert len(inp) == n, \
+ f"Not enough arguments available {len(inp)} vs needed {n}\n {stack} {inp}"
# Figure out the local variables that might be relevant.
relevant_comp = dict()
- for a in args:
+ for a in inp:
if isinstance(a, ScopeVariable):
relevant_comp[id(a)] = a
if rcd := getattr(a, 'relevant_comp', None):
@@ 71,28 76,26 @@ class StackCalc:
# If it won't deal with variables, extract the values for it.
if not getattr(val, 'with_vars', None):
- args = [(a.val if isinstance(a, BaseComponent) else a)
- for a in args]
- assert not any(isinstance(a, BaseComponent) for a in args)
+ inp = [(a.val if isinstance(a, BaseComponent) else a)
+ for a in inp]
+ assert not any(isinstance(a, BaseComponent) for a in inp)
# Actually calculate the type, return new stack and result.
stack, *tc_code = (
- tp_fun(self, code, vs, args, into)
+ tp_fun(self, code, vs, inp, into)
if getattr(val, 'mac', None) else
- tp_fun(self, vs, args))
+ tp_fun(self, vs, inp))
- assert_acceptable_vals(stack, args, rest, code, var)
+ assert_acceptable_vals(stack, inp, rest, code, var)
if fun := getattr(val, 'deal_relevant_comp', None):
- fun(relevant_comp, args)
+ fun(relevant_comp, inp)
for el in stack: # Remember all the relevant local variables.
if fun := getattr(el, 'deal_relevant_comp', None):
- fun(relevant_comp, args)
+ fun(relevant_comp, inp)
el.relevant_comp = relevant_comp
return (rest + stack, *tc_code)
- assert_acceptable_vals(stack, val)
-
return stack[:-1] + [var], var # No calculation needed.
special_fun= {'+', '-', '*', '/', '%', '>', '<'}
@@ 115,7 118,7 @@ class StackCalc:
continue
if word[:1] == '.' or word in self.special_fun: # It's a component.
- assert len(stack) >= 1
+ assert len(stack) >= 1, "Trying to access, but empty stack."
assert_acceptable_vals((stack[-1],), stack)
got = stack[-1].get_comp(word[1:] if word[:1]=='.' else word)
@@ 130,7 133,7 @@ class StackCalc:
# It is a variable, or accesses something.
if insert := getattr(got.val, 'insert_code', None):
- assert getattr(got.val, 'tp_calc', None) is None
+ assert getattr(got.val, 'tp_calc', None) is None, "BUG: cannot have both `insert_code` and `tp_calc`."
plus, stack = insert(self, code, vs, stack)
inserted = plus + inserted
else:
@@ 138,4 141,5 @@ class StackCalc:
assert_acceptable_vals(otp, "Producing type-calced-code.")
for el in otp: # Insert the tc code.
into(el)
+
assert_acceptable_vals(stack, got, code)