Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
0f58703
enable logging
andrew4328 Apr 1, 2026
1492216
havent run that yet
andrew4328 Apr 2, 2026
8d9f283
m
andrew4328 Apr 2, 2026
cc45f78
add assertion against bad for loops
andrew4328 Apr 2, 2026
c710e04
remove [] from list because it has n^2 performance but doesnt look li…
andrew4328 Apr 2, 2026
e29256d
profile 2
andrew4328 Apr 3, 2026
9f0afde
merge doesnt look unreasonable, just lots of legitimate phi types bei…
andrew4328 Apr 3, 2026
73e8d66
try to reduce number of phi types
andrew4328 Apr 3, 2026
7239c44
literally nothing
andrew4328 Apr 3, 2026
1bac9ea
seems to work but doesnt matter
andrew4328 Apr 3, 2026
85b979e
remove reification workarounds
andrew4328 Apr 3, 2026
30c6bdf
working to eliminate redundant phi allocations
andrew4328 Apr 3, 2026
ccee037
counts are wrong already, what went wrong...
andrew4328 Apr 3, 2026
e260c34
that lazy .with-phi call in ascript is REALLY EXPENSIVE. going to rem…
andrew4328 Apr 3, 2026
a4f5960
issue
andrew4328 Apr 8, 2026
0b2b199
OK, working on active branch
andrew4328 Apr 8, 2026
ceb17a5
that .with-phi seems to be completely unnecessary
andrew4328 Apr 8, 2026
22a1bcf
array allocator was hashtable
andrew4328 Apr 8, 2026
6e84dfa
remove config flags from tests
andrew4328 Apr 8, 2026
b0e7cc1
51 regressions. now to look into GC hooks
andrew4328 Apr 8, 2026
286eec9
just debug normally
andrew4328 Apr 8, 2026
662b16f
new strategy turn .lookup phi from O(n) to O(1)
andrew4328 Apr 8, 2026
7431107
move to U64 for ids first
andrew4328 Apr 8, 2026
624fe89
gradual
andrew4328 Apr 8, 2026
75fc3f3
small fixes
andrew4328 Apr 8, 2026
b122918
OK, now fix regressions
andrew4328 Apr 8, 2026
3b6ae2d
fix small issues
andrew4328 Apr 8, 2026
6350f72
working forward
andrew4328 Apr 9, 2026
0600583
53 regressions
andrew4328 Apr 9, 2026
347c4fe
down to 11 regressions, GC is working with fast Phi Ids
andrew4328 Apr 9, 2026
1bda788
10 regressions
andrew4328 Apr 9, 2026
eac85f7
GC is a bit slower now but only 3-4x
andrew4328 Apr 9, 2026
6f69959
skip all lm tests
andrew4328 Apr 9, 2026
dc3b449
delete dead code and use existing testing conventions
andrew4328 Apr 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7,487 changes: 3,847 additions & 3,640 deletions BOOTSTRAP/cli.c

Large diffs are not rendered by default.

29 changes: 21 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ LSTSFLAGS = MALLOC_CHECK_=3
# recommendation: ulimit -s unlimited

dev: install-production
#lm --showalloc SRC/unit-tctx-core.lsts > out.txt
#lm --showalloc SRC/unit-prop-core.lsts > out.txt
#lm --showalloc SRC/unit-ascript-core.lsts > out.txt
#lm --showalloc SRC/index.lsts > out.txt
lm tests/promises/typechecking/misc-linear-error-1.lsts > out.txt
gcc tmp.c;
lm tests/promises/vector/constructor.lsts
#time lm --showalloc SRC/unit-type-core.lsts > out.txt
#time lm --showalloc SRC/unit-tctx-core.lsts > out.txt
#time lm --showalloc SRC/unit-prop-core.lsts > out.txt
#time lm --showalloc SRC/unit-ascript-core.lsts > out.txt
#time lm --showalloc SRC/index.lsts > out.txt
#time lm --showalloc SRC/dev-index.lsts > out.txt
gcc tmp.c
./a.out

build: compile-production
Expand All @@ -28,8 +30,15 @@ build: compile-production
deploy: build smoke-test
deploy-lite: build smoke-test-lite

valgrind: install-bootstrap
valgrind --tool=callgrind lm --v2 SRC/index.lsts
gprofng: install-production
gprofng collect app lm SRC/dev-index.lsts

gprofng-view:
gprofng display text -functions test.1.er > gprofng.view
nano gprofng.view

valgrind: install-production
valgrind --tool=callgrind lm SRC/dev-index.lsts

valgrind-view:
callgrind_annotate callgrind.out.18778
Expand Down Expand Up @@ -60,17 +69,21 @@ compile-production: compile-bootstrap

install-production: compile-production
ifeq ($(shell test -w /usr/local/bin; echo $$?), 0)
cp production /usr/local/bin/lm-production
mv production /usr/local/bin/lm
else
mkdir -p $${HOME}/.local/bin
cp production $${HOME}/.local/bin/lm-production
mv production $${HOME}/.local/bin/lm
endif

install-bootstrap: compile-bootstrap
ifeq ($(shell test -w /usr/local/bin; echo $$?), 0)
cp bootstrap.exe /usr/local/bin/lm-bootstrap
mv bootstrap.exe /usr/local/bin/lm
else
mkdir -p $${HOME}/.local/bin
cp bootstrap.exe $${HOME}/.local/bin/lm-bootstrap
mv bootstrap.exe $${HOME}/.local/bin/lm
endif

Expand Down
32 changes: 0 additions & 32 deletions SRC/ascript-ascript-integrated.lsts

This file was deleted.

26 changes: 0 additions & 26 deletions SRC/ascript-ascript-normal.lsts

This file was deleted.

8 changes: 7 additions & 1 deletion SRC/ascript-ascript.lsts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ let .ascript(tctx: TypeContext?, t: AST, tt: Type): TypeContext? = (
exit-error("Type Ascription Inequality\n\{typeof-term-normal(t)} does not imply \{norm-tt}", t);
}
};
if tt.slot(c"Phi::Id",1).l1.simple-tag != prev-tt.slot(c"Phi::Id",1).l1.simple-tag {
if tt.slot(c"Phi::Id",1).l1.simple-id != prev-tt.slot(c"Phi::Id",1).l1.simple-id {
tctx = tctx.phi-move(prev-tt, t);
}
};
Expand All @@ -22,5 +22,11 @@ let .ascript(tctx: TypeContext?, t: AST, tt: Type): TypeContext? = (
let ascript-force(t: AST, tt: Type): Nil = (
add-concrete-type-instance(tt, t);
ascript-natural(t, tt);

# these initializations are necessary to prevent stale phi types
# I don't remember why that is, but just try removing them and debug from there
type-index-normal = type-index-normal.bind(t, ta);
type-index-denormal = type-index-denormal.bind(t, ta);

types-have-changed = true;
);
2 changes: 1 addition & 1 deletion SRC/ascript-tctx-resurrect.lsts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
let .resurrect(tctx: TypeContext?, tt: Type, t: AST): (TypeContext?, Type) = (
# TODO: fix tt2, tt3 workaround which was for linear variable bug
# NOTE: make sure to create a promise test covering this phi/linear bug
let phi-id = tt.slot(c"Phi::Id",1).l1.simple-tag;
let phi-id = tt.slot(c"Phi::Id",1).l1.simple-id;
if non-zero(phi-id) {
let tt2 = tctx.with-phi(tt, t);
let phi-state = tt2.slot(c"Phi::State",1).l1;
Expand Down
18 changes: 7 additions & 11 deletions SRC/dev-index.lsts
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@

import SRC/unit-util.lsts;
import SRC/dev-unit-type-core.lsts;
import SRC/dev-unit-ast-core.lsts;
import SRC/dev-unit-tctx-core.lsts;
import SRC/dev-unit-prop-core.lsts;
import SRC/dev-unit-ascript-core.lsts;
import SRC/dev-unit-typecheck-core.lsts;
import SRC/dev-unit-backend-core.lsts;
import SRC/unit-type-core.lsts;
import SRC/unit-ast-core.lsts;
import SRC/unit-tctx-core.lsts;
import SRC/unit-prop-core.lsts;
import SRC/unit-ascript-core.lsts;
import SRC/unit-typecheck-core.lsts;
import SRC/unit-backend-core.lsts;
import SRC/unit-main-core.lsts;

import PLUGINS/FRONTEND/LSTS/dev-index.lsts;
import PLUGINS/BACKEND/C/dev-index.lsts;
import PLUGINS/FRONTEND/C/index.lsts;
2 changes: 1 addition & 1 deletion SRC/dev-unit-ascript-core.lsts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ import SRC/ascript-type-index.lsts;
import SRC/dev-ascript-concrete-index.lsts;
import SRC/ascript-datatype-index.lsts;
import SRC/ascript-with-only-datatype.lsts;
import SRC/ascript-ascript-integrated.lsts;
import SRC/ascript-ascript.lsts;
import SRC/ascript-tctx-resurrect.lsts;
2 changes: 1 addition & 1 deletion SRC/prop-phi-override.lsts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

let .phi-override(tctx: TypeContext?, dst: Type, src: Type, blame: AST): TypeContext? = (
let dst-id = dst.slot(c"Phi::Id",1).l1.simple-tag;
let dst-id = dst.slot(c"Phi::Id",1).l1.simple-id;
let src-tt = src.slot(c"Phi::State",1).l1;
if non-zero(dst-id) and non-zero(src-tt) {
tctx = tctx.bind-phi(dst-id, src-tt, blame, dst.is-t(c"GlobalVariable",0));
Expand Down
9 changes: 5 additions & 4 deletions SRC/prop-tctx-least-upper-bound.lsts
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,23 @@ let .least-upper-bound(tctx: TypeContext?, left: Type, right: Type, blame: AST):
if ps.is-some then rt = ts(ltag,ps.get-or-panic);
}
);
Tuple{ first:TId{lid=id}, second:TId{rid=id} } => if lid==rid then rt = left;
Tuple{ first:TAny{}, second:TAny{} } => ();
_ => ();
};

if non-zero(rt) and left.is-t(c"Phi::State",1) and right.is-t(c"Phi::State",1) {
# Merge and bind new phi state
let new-phi-state = tctx.phi-merge(left.slot(c"Phi::State",1).l1, right.slot(c"Phi::State",1).l1, blame);
let new-phi-id = uuid();
let new-phi-id = iuid();
tctx = tctx.bind-phi(new-phi-id, new-phi-state, blame);

# Move linear variables in left and right types
tctx = tctx.bind-phi(left.slot(c"Phi::Id",1).l1.simple-tag, left.slot(c"Phi::State",1).l1.move-linear, blame);
tctx = tctx.bind-phi(right.slot(c"Phi::Id",1).l1.simple-tag, right.slot(c"Phi::State",1).l1.move-linear, blame);
tctx = tctx.bind-phi(left.slot(c"Phi::Id",1).l1.simple-id, left.slot(c"Phi::State",1).l1.move-linear, blame);
tctx = tctx.bind-phi(right.slot(c"Phi::Id",1).l1.simple-id, right.slot(c"Phi::State",1).l1.move-linear, blame);

# Add Phi::Id to least-upper-bound
rt = rt && t1(c"Phi::Id",t0(new-phi-id));
rt = rt && t1(c"Phi::Id",ti(new-phi-id));
};

if left.is-t(c"Phi::State",1) or right.is-t(c"Phi::State",1) and not(rt.is-t(c"Phi::Id",1))
Expand Down
4 changes: 2 additions & 2 deletions SRC/tctx-bind.lsts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ let .bind-global(tctx: TypeContext?, k: CString, nt: Type, dt: Type, blame: AST)
tctx
);

let .bind-phi(tctx: TypeContext?, k: CString, kt: Type, blame: AST): TypeContext? = (
let .bind-phi(tctx: TypeContext?, k: U64, kt: Type, blame: AST): TypeContext? = (
Some(TypeContext(
tctx.get-or(mk-tctx()).tctx,
cons( PhiContextRow(k,kt,blame,false,tctx-currently-processing-globals) , tctx.get-or(mk-tctx()).pctx ),
Expand All @@ -41,7 +41,7 @@ let .bind-phi(tctx: TypeContext?, k: CString, kt: Type, blame: AST): TypeContext
));
);

let .bind-phi(tctx: TypeContext?, k: CString, kt: Type, blame: AST, is-global: Bool): TypeContext? = (
let .bind-phi(tctx: TypeContext?, k: U64, kt: Type, blame: AST, is-global: Bool): TypeContext? = (
Some(TypeContext(
tctx.get-or(mk-tctx()).tctx,
cons( PhiContextRow(k,kt,blame,false,is-global) , tctx.get-or(mk-tctx()).pctx ),
Expand Down
6 changes: 3 additions & 3 deletions SRC/tctx-definition.lsts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ let .release(t: TypeContextRow): Nil = (
mark-as-released(t);
);

type PhiContextRow zero NullPhiContextRow implies MustRetain, MustRelease = NullPhiContextRow | PhiContextRow { phi-id: CString, phi-tt: Type, blame: AST, dead-on-arrival: Bool, is-global: Bool };
type PhiContextRow zero NullPhiContextRow implies MustRetain, MustRelease = NullPhiContextRow | PhiContextRow { phi-id: U64, phi-tt: Type, blame: AST, dead-on-arrival: Bool, is-global: Bool };
let .retain(t: PhiContextRow): PhiContextRow = (
if t.discriminator-case-tag==(t as Tag::PhiContextRow).discriminator-case-tag {
mark-as-released((t as Tag::PhiContextRow).phi-tt.retain);
Expand Down Expand Up @@ -85,10 +85,10 @@ let .blame-or-zero(tr: TypeContextRow): AST = (
}
);

let .phi-id-or-zero(tr: PhiContextRow): CString = (
let .phi-id-or-zero(tr: PhiContextRow): U64 = (
match tr {
PhiContextRow{ phi-id=phi-id } => phi-id;
_ => c"";
_ => 0;
}
);
let .phi-tt-or-zero(tr: PhiContextRow): Type = (
Expand Down
4 changes: 2 additions & 2 deletions SRC/tctx-lookup.lsts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ let .lookups(trs: List<TypeContextRow>, key: CString): Vector<TypeContextRow> =
default
);

let .lookup-phi(tctx: TypeContext?, key: CString): PhiContextRow = tctx.get-or(mk-tctx()).pctx.lookup(key);
let .lookup(trs: List<PhiContextRow>, key: CString): PhiContextRow = (
let .lookup-phi(tctx: TypeContext?, key: U64): PhiContextRow = tctx.get-or(mk-tctx()).pctx.lookup(key);
let .lookup(trs: List<PhiContextRow>, key: U64): PhiContextRow = (
let default = NullPhiContextRow;
let continue = true;
while non-zero(trs) and continue {
Expand Down
2 changes: 1 addition & 1 deletion SRC/tctx-phi-append.lsts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ let .phi-append-dead-on-arrival(tctx-primary: TypeContext?, tctx-secondary: Type
);

let .phi-append(tctx-primary: List<PhiContextRow>, tctx-secondary: List<PhiContextRow>, dead-on-arrival: Bool): List<PhiContextRow> = (
let seen = {} : Hashtable<CString,Bool>;
let seen = {} : Hashtable<U64,Bool>;
for list pr1 in tctx-secondary {
if not(seen.has-key(pr1.phi-id-or-zero)) {
let pr2 = tctx-primary.lookup(pr1.phi-id-or-zero);
Expand Down
16 changes: 8 additions & 8 deletions SRC/tctx-phi-fresh.lsts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ let .phi-fresh(tctx: TypeContext?, tr: TypeContextRow): (TypeContext?, TypeConte
TypeContextRow{ key=key, nt=nt, dt=dt, blame=blame } => (
nt = tctx.with-phi(nt, blame);
dt = tctx.with-phi(dt, blame);
let phi-id = nt.slot(c"Phi::Id",1).l1.simple-tag;
if not(non-zero(phi-id)) then phi-id = dt.slot(c"Phi::Id",1).l1.simple-tag;
let phi-id = nt.slot(c"Phi::Id",1).l1.simple-id;
if not(non-zero(phi-id)) then phi-id = dt.slot(c"Phi::Id",1).l1.simple-id;
let phi-state = nt.slot(c"Phi::State",1).l1;
if not(non-zero(phi-state)) then phi-state = dt.slot(c"Phi::State",1).l1;
if non-zero(phi-id) and non-zero(phi-state) {
let new-phi-id = uuid();
let new-phi-id = iuid();
tctx = tctx.bind-phi(new-phi-id, phi-state, blame);
nt = nt.without-slot(c"Phi::Id",1).extend( t1(c"Phi::Id",t0(new-phi-id)) );
dt = dt.without-slot(c"Phi::Id",1).extend( t1(c"Phi::Id",t0(new-phi-id)) );
nt = nt.without-slot(c"Phi::Id",1).extend( t1(c"Phi::Id",ti(new-phi-id)) );
dt = dt.without-slot(c"Phi::Id",1).extend( t1(c"Phi::Id",ti(new-phi-id)) );
};
(tctx, TypeContextRow(key,nt,dt,blame))
);
Expand All @@ -22,12 +22,12 @@ let .phi-fresh(tctx: TypeContext?, tr: TypeContextRow): (TypeContext?, TypeConte

let .phi-fresh(tctx: TypeContext?, nt: Type, blame: AST): (TypeContext?, Type) = (
nt = tctx.with-phi(nt, blame);
let phi-id = nt.slot(c"Phi::Id",1).l1.simple-tag;
let phi-id = nt.slot(c"Phi::Id",1).l1.simple-id;
let phi-state = nt.slot(c"Phi::State",1).l1;
if non-zero(phi-id) and non-zero(phi-state) {
let new-phi-id = uuid();
let new-phi-id = iuid();
tctx = tctx.bind-phi(new-phi-id, phi-state, blame);
nt = nt.without-slot(c"Phi::Id",1).extend( t1(c"Phi::Id",t0(new-phi-id)) );
nt = nt.without-slot(c"Phi::Id",1).extend( t1(c"Phi::Id",ti(new-phi-id)) );
};
(tctx, nt)
);
4 changes: 2 additions & 2 deletions SRC/tctx-phi-initialize.lsts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ let .phi-initialize(tctx: TypeContext?, tt: Type, blame: AST): (TypeContext?, Ty
(tctx, tand(new-conjugate))
);
TGround{tag:c"Phi::State",parameters:[init-tt..]} => (
let phi-id = uuid();
let phi-id = iuid();
tctx = tctx.bind-phi(phi-id, init-tt, blame);
(tctx, t1(c"Phi::Id",t0(phi-id)))
(tctx, t1(c"Phi::Id",ti(phi-id)))
);
TGround{tag:c"Cons",parameters:[p2..p1..]} => (
(tctx, p1) = tctx.phi-initialize(p1, blame);
Expand Down
2 changes: 1 addition & 1 deletion SRC/tctx-phi-move-all.lsts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

let .phi-move-all(tctx: TypeContext?): TypeContext? = (
let seen = {} : Hashtable<CString,Bool>;
let seen = {} : Hashtable<U64,Bool>;
for list pr in tctx.get-or(mk-tctx()).pctx {
if not(seen.has-key(pr.phi-id-or-zero)) {
if pr.phi-tt-or-zero.is-linear-live {
Expand Down
3 changes: 1 addition & 2 deletions SRC/tctx-phi-move.lsts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
let .phi-move(tctx: TypeContext?, tt: Type, blame: AST): TypeContext? = (
tt = tctx.with-phi(tt, blame);
if not(tctx.get-or(mk-tctx()).is-blob) then {
let phi-id = tt.slot(c"Phi::Id",1).l1.simple-tag;
let phi-id = tt.slot(c"Phi::Id",1).l1.simple-id;
let phi-state = tt.slot(c"Phi::State",1).l1;
if non-zero(phi-id) and non-zero(phi-state) {
tctx = tctx.bind-phi(phi-id, phi-state.move-linear, blame);
let pm = tctx.lookup-phi(phi-id);
}
};
tctx
Expand Down
7 changes: 5 additions & 2 deletions SRC/tctx-unify.lsts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ let unify-inner(fpt: Type, pt: Type, blame: AST): Maybe<TypeContext> = (
Tuple{ first:TAnd{ lconjugate=conjugate }, second:TAnd{ rconjugate=conjugate } } => (
let result = yes;
let ri = 0_sz;
let phi-id = c"";
let phi-id = 0_u64;
let phi-state-in = ta;
let phi-state-out = ta;
for vector lc in lconjugate {
Expand All @@ -44,7 +44,7 @@ let unify-inner(fpt: Type, pt: Type, blame: AST): Maybe<TypeContext> = (
TGround{tag:c"MustNotFresh"} => ();
TGround{tag:c"Phi::Transition", parameters:[phi-to..phi-from..]} => (
for vector st in rconjugate { match st {
TGround{tag:c"Phi::Id",parameters:[TGround{new-phi-id=tag}..]} => (
TGround{tag:c"Phi::Id",parameters:[TId{new-phi-id=id}..]} => (
phi-id = new-phi-id;
);
TGround{tag:c"Phi::State",parameters:[new-phi-state..]} => (
Expand Down Expand Up @@ -158,6 +158,9 @@ let unify-inner(fpt: Type, pt: Type, blame: AST): Maybe<TypeContext> = (
first:TGround{ltn=tag, lps=parameters},
second:TGround{rtn=tag, rps=parameters}
} => if (ltn==rtn or (ltn.has-suffix(c"::") and rtn.has-prefix(ltn))) then { ctx = unify(lps,rps,blame) };

Tuple{ first:TId{lid=id}, second:TId{rid=id} } => if lid == rid then yes else no;

_ => ();
};
ctx
Expand Down
4 changes: 2 additions & 2 deletions SRC/tctx-with-phi-id-if-phi-state.lsts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

let .with-phi-id-if-phi-state(tctx: TypeContext?, tt: Type, blame: AST): (TypeContext?, Type) = (
if tt.is-t(c"Phi::State",1) {
let phi-id = uuid();
let phi-id = iuid();
tctx = tctx.bind-phi(phi-id, tt.slot(c"Phi::State",1).l1, blame);
tt = tt && t1(c"Phi::Id",t0(phi-id));
tt = tt && t1(c"Phi::Id",ti(phi-id));
};
(tctx, tt)
);
Loading
Loading