To-do for MicroTiML
Tracks 100+ completed and pending tasks for a research programming language compiler, typechecker, examples, and proofs.
What this file does
Tracks 100+ completed and pending tasks for a research programming language compiler, typechecker, examples, and proofs.
When to use it
- Planning the next development milestones for a TiML-like language
- Debugging known issues in type inference, unification, or module systems
- Adding new examples or standard library features to a TiML compiler
- Reviewing abandoned or superseded design decisions for reference
Assumes this stack
- Remove bsort from Eq
-
msginstr_errorshould be of (string list) - split
casesyntax intocase,sumcaseandunpack -
caseandunpackshould allow omitting return-clause and try to forget unescapable variables (like whatletdoes) - Distill the
bindpattern - Disallow impredicative universal types
- Type inference
- Idx inference
- (Kind-of) Allow
datatypeto have idx arguments that do not change. - Multi-argument idx functions.
- Add an optional idx to
Quan, to link the remaining unification variables in types and the witnesses found by the Master Theorem solver. - Infer by Master Theorem then check.
- Single variable Master Theorem case.
- Error line number on multiple files.
- Make linking between inferred existential variable values and types better.
- Copy function signature annotation to case annotation
- (Abondoned. No problem.) Unit and product types are required to define datatypes. 17. Remove unit and product types from the language, and have standard library.
- Example: Tree flatten.
- Example: Insertion sort.
- Have reference and arrays.
- RB-tree insertion.
- RB-tree lookup.
- Braun tree insertion.
- A bug of position reporting when I change bigO spec of msort in msort.timl from
$m * $n * log2 $nto$n * log2 $n. -
return _ usingworks butreturn usingdoes not in msort.timl and tree.timl. - Change syntax order of function name and
tdeclares. - Be able to infer for
tree_mapandtree_foldl. - (Partially) Have module system.
Road map to add module system:
- Have a barebone module system with only modules, signatures, sealing, functors and
open. No hierarchy (embeded modules), module alias, signature alias,where/sharing,include. - Combine name-resolve and typecheck.
- Combine cctx and tctx into tctx.
- (\Abondoned.) Combine idx and type into constructors, sort and kind into kind, Combine sctx and kctx into kctx.
- Add record types.
- Add singleton kinds, dependent record kinds, dependent arrow kinds.
- Elaborate modules and signatures into core language.
- Have a barebone module system with only modules, signatures, sealing, functors and
- Bug of type inference in tree_append_rlm. The inferred type has
{n} tree treeand{n} list list. - Put
Unitback to mtype frombase_typebecauseUnitis not a base type likeIntbut a structural building block. - Have a good error message when insertion_sort.timl/
insertdoes not have the needed return-annotation oncase. - Be able to infer for
insertion_sort. - (Solved by new unification framework)
unify's(UVar, UVar)case could be dangerous: shift_invis may not be transactional, and there is no circularity check. - Have a standard library.
- Automatically generate premises in
(VarP, Never)case ofmatch_ptrn, from complement cover of previous rules. -
caseshould also copyfun'sreturnclause even withoutusing. - (Abondoned. No problem.)
aspattern may have a problem inbalance_left. - Bug: redundancy checker runs forever on
balance_left. - rbt.timl typecheckes when using ForgetError-less
substand ForgetError-fullforget. Investigate why. -
find_habitantcan further simplify covers and speed up. - Have
type =type aliasing. - Maximally insertion of index arguments.
- Maximally insertion of index arguments in patterns.
- nouvar-expr/passp/Imply/_ is not sound, possibly losing information.
- (Solved by new unification framework)
subst_invis_no_throwshould be implemented in a safe way where uvars that can see the target variable are unified with a new shifted uvars that cannot see it, andbring_forward_anchorneeds to be more sophisticated to only put new anchor when there is no shift (and the notifier inExistsneeds to do some shift) because now not every uvar has an anchor. - Braun tree extraction.
- rename "peel_" to "collect_".
- Register admitted things.
- Make SMT batch response parsing smarter (do not check response length beforehand)
- Simplify MaxI using SMT solver.
- Have binary search with arrays.
- Have binary heap with arrays.
- Have in-place merge sort with arrays.
- Have k-median search with arrays.
- Investigate amortized complexity analysis.
- Prove in Coq.
- Infer
BigOarity. - Have built-in indexed
uint. - Pretty-print to SML.
- Combine cctx and tctx.
- Add <> notation.
- Add a return clause in
Caseto mean the time including the matchee. - Amortized complexity of queue implementation by two stacks.
- Infer type according to pattern.
- (No longer exists.) Wrongly inferred
T_insert_delete_seq_0to be (fn n => $n) without the2.0 + 48.0 * $nannotation. The source of the problem: unsoundness in bigO-solver.sml/solve_exists(). - Have some Nat/Time inference.
- Unify
UnOpI,DivIandExpI. - Unify
TrueandFalse. - Change
unify_stois_sub_sort. - Should apply solvers and check no-uvar after every module, not every file (unless we enforce one-module-per-file policy).
- Move VC openings from
check_decltocheck_decls. -
substshould do lazy shifting, not eager. - The last two examples in bigO-evolve.timl about using
idxinstead ofabsidxdoes not work now. - Simplify unused
forallinprop. The unused foralls are Big-O premises. -
BigOEvolveSealedin bigO-evolve.timl does not work yet. - if-then-else and list syntax.
- (No longer needed because uvars can be retrieved from modules now) Restore the version of
link_sigin revision 00ba072, because a module may have uvars before sealing, and uvars cannot be retrieved from modules. - Big-O solver should heuristically distinguish "defining" side of
TimeFunuvars from the "using" side, by the rule-of-thumb that only_ <= f xis a defining constraint off. - Do a module dependent analysis of each module and only bring the needed modules into
gctxVC context. - Have double-linked lists.
- rbt6.timl: absidx sort
Timeinference error inIntKey. - Currently
absidx ... with ... endis "scoped abstract index". We should have "unscoped" or "module-scoped" abstract indexabsidx id = ...so within the moduleid's definition is visible but outside the module it is not. - Make
kind's sorts dependent, or only usebsortinkind. - Generate typing derivations.
Road map (a translation validation (i.e. derivation reconstruction) approach):
- Generate type-annotation TiML syntax
- Translate it to type-annotated micro-TiML syntax
- Reconstruct micro-TiML typing derivations from type-annotated micro-TiML syntax
- The micro-TiML to assembly-TiML compilation should also use this approach
- Remove annotations on
case(at least in a mode). -
datatypecan introduce index variable names at the first line for every constructor. -
find_habis too slow on array-msort.timl and array-msort-inplace.timl - A new unification framework ("skolemized unification"): every unification variable denotes a closed entity, which could be a lambda abstraction. For example, when we see type annotation [a : ] in the sorting context [x:Nat, y:Time], we introduce a uvar ?1 of kind [Nat => Time => Type], and replace the "" with [AppV ?1 [x,y]]. When we try to unify [AppV ?1 [x,y]] with [int], in principle we can't conclude that [?1 = int]. But exploiting specific knowledge in this language, we can. When we can have such a definitive conclusion, we refine ?1 to be [int]; but when we can't have a definitive conclusion when doing unification, we should record it as a VC. For example, when we try to unify [AppV ?1 [x,y]] with [AppV ?2 [x,y]], we should put [AppV ?1 [x,y] = AppV ?2 [x,y]] in VC, instead of conclude that [?1 = ?2] (unless we want to do incomplete, over-aggressive unification).
- SML supports datatypes instantiated with different type arguments within a constructor, such as [datatype 'a ls = Nil | Cons of 'a * ('a * 'a) ls]. TiML's typechecker also supports this. So TiML's proof should also support this. It has usage in for example Okasaki's implicit queue (thesis Chapter 8).
- (Abondoned. Non-constant subtracter is needed to support minus of
nattype) Change minus from a binop to an unop where the second operand can only be constant. - Investigate array-msort-in-place.
- Generalization has some problems with higher-order uvars.
- Simplify modules in output.
- Rename [long_id]'s [ID] to "Bound" and [QID] to "Free", in accordance with locally nameless representation.
- Add native booleans. Add more integer operations (including comparisons). Add more nat operations.
- Add example links to website.
- Remove assert_b and assert_b_m to make sure when assertion are turned off no computation will be wasted.
- Add ELength.
- eq_mt()/TDatatype needs to be implemented to allow instantiating dynamic-table.timl.
- Add negative examples.
- Argument module names of functors are put into global context, which may result in name conflicts. Should prefix argument module names with the functor names.
- Complete parser support for string literals and unescape().
- If a primitive shouldn't be redefined (especially base type names because type names appear in feedback messages), it should be made a keyword in timl.lex.
- Propogate return clauses through [ifdec] and [if]; let those time specs mean entire time including the matchee.
- Have sprintf.
- Check no-UVar after typechecking.
- Write
simp_mtusing visitor. - A full storage interface should support the following containers:
- map to nullable primitives
- map to map
- map to tuples
- map to tuples of maps
- indexed vector of primitives (vectors should guarantee elements are always well-formed and allow value types not inhabited by zero)
- indexed vector of tuples (the problem with a vector of tuples is that there is no atomic push_back operation)
- indexed vector of maps
- indexed vector of tuples of maps
- ref of primitives
- ref of tuples
- array of primitives
- array of tuples
- indexed nat
- unindexed vectors as values of the above containers. An access to an element of an unindexed vector should include a length check.
- TiML should support state polymorphism (i.e. treating the entire state as an index) as MicroTiML, in order to support the 'for' combinator for stateful computations.
- Since TiML now has full support for record idx (IState) and record types (TRecord), we should change TRecord to be a type constructor that given a record idx constructs a record type. Then TiML is as powerful as Ur/Web!
To-do for MicroTiML
- remove let x = ... when x is "_", because such case can only be from translation of wildcard patterns
- remove duplicate EAsc and EAscTime
- analysing the form of expr is complicated by the pervasion of EAscType and EAscTime; need some principled way to transparently ignore EAscType/Time.
- dynamic-table.timl needs to be instantiated to be tested by MicroTiML compiler
- tc() should add annotations only when specific flags are turned on; the client that turns on these flags should consume the annotations to prevent them from polluting later translations.
- Add level limits to export_t and export_e.
- Add a pass to remove annotations on EVar, TVar and VarI after cc().
- Uniquefy variable names.
- check_CPSed_expr() should also check types.
- anf_decls() shouldn't alway use "x" as the new variable name, because it will replace other meaningful names after post_process(); it should take suggestions from surrounding ELet.
- Add a simplification for ECase where if the two branches are identical and don't mention the local variable, combine them and remove ECase.
- Remove datatype "micro_timl" and rename "micro_timl_ex" to "micro_timl".
- Rename "micro-timl/" to "compiler/".
- Add "let nat {i} = x in ..." to name the index of nat.
- Add register-file polymorphism so that EVM snippets for new_array and string_concat can be shared instead of inlined.
- pattern-ex.sml/remove_deep_many() should handle empty datatypes.
- The changed EVM typechecker (checking ASCTIME without later premises) still works on example recursive functions annotated only with case's return clause, because TiML typechecker added EAscTime (_, return - adjust) to everybranch. This trick won't work when the truthfulness of 'return >= adjust' depends on local premises. A thorough solution should be having bi-directional typechecking on every level and in the 'check type' mode, passing in (total_time_spec, time_accumulated_already), and allowing time_accumulated_already to be larger than total_time_spec, because later code can introduce a 'false' premise.
- This code in EtherDelta.etiml causes cost bug after CPS: fun trade (tokenGet : address, amountGet : uint, tokenGive : address, amountGive : uint, expires : uint, nonce : uint, user : address, v : uint8, r : bytes32, s : bytes32, amount : uint) = (amount is in amountGet terms) let hash : bytes32 = sha256(this, tokenGet, amountGet, tokenGive, amountGive, expires, nonce); if (not ( (* (orders[user][hash] || ecrecover(sha3("\x19Ethereum Signed Message:\n32", hash),v,r,s) == user) && ) ( block.number <= expires && ) safeAdd(orderFills[user][hash], amount) <= amountGet )) then throw end; ( tradeBalances(tokenGet, amountGet, tokenGive, amountGive, user, amount); ) ( set orderFills[user][hash] safeAdd(orderFills[user][hash], amount) ) ( emit Trade(tokenGet, amount, tokenGive, amountGive * amount / amountGet, user, msg.sender) ) ( ;(orderFills[user][hash], tokens[tokenGet][msg.sender], tokens[tokenGet][user], tokens[tokenGet][msg.sender], tokens[tokenGet][user], tokens[tokenGive][msg.sender], tokens[tokenGive][user]) *) halt 0x555
- There is a bug in BlindAuction.etiml that when inline
let b = placeBid(msg.sender, value)typechecking after translation generates two wrong VCs. - Functions below CPS should have multiple arguments to avoid tuple-related costs.
To-do for Examples:
- Binary search with arrays.
- binary heap with arrays.
- In-place merge sort with arrays.
- k-median search with arrays.
- Quicksort.
- Dijkstra algorithm.
- Two-stack queue (amortized).
- Double-linked lists.
- Union-find (amortized).
- Some example showcasing the flexibility of "size".
What's inside
Three sections: MicroTiML compiler tasks, example tasks, and sub-tasks for module system and storage interface. Over 100 checklist items.
Change this for your project
- Replace
wangpengmit/timlwith your own repository name - Replace file paths like
array-msort.timlwith your own example files - Replace
msort.timlandtree.timlwith your own test files - Replace
EtherDelta.etimlandBlindAuction.etimlwith your own contract examples
Where it goes
Keep it in your repository where the agent or team that needs it will read it.
Worth borrowing
- Separate language core tasks from example tasks for clarity
- Mark abandoned decisions explicitly to avoid revisiting dead ends
- Use sub-bullet roadmaps for complex features like module system
Related Documents
Setup & Deployment Checklist
Guides you through 10 phases to set up, test, deploy, and customize a content agent system using OpenRouter and Streamlit.
RealDiag Demo Video Script
Provides a complete 5-7 minute demo video script for a clinical decision support tool, including timing, visual cues, and production notes.
š± Mobile Phone Preview - Quick Start
Walks you through four ways to preview a React Native Expo app on real devices and emulators, plus a testing checklist and troubleshooting guide.
š Product Hunt Launch Prep
Provides a Product Hunt launch checklist, listing copy, and newsletter template for an open-source AI vulnerability database.