xo-expression type-inference [wip]

This commit is contained in:
Roland Conybeare 2025-07-25 10:42:15 -04:00
commit 16c08b2f96
3 changed files with 90 additions and 0 deletions

View file

@ -0,0 +1,16 @@
Random notes.
Type inference.
Expressions represent parsed abstract syntax trees.
We use the same data structure to represent syntax trees both before and after
type inference.
We record each Expression's type using a type_ref instance.
A type_ref does two things:
1. gives the expression's type a unique name
2. records expression's concrete type once type infrerence has completed.
Type inference resolves each Expression's type to a concrete TypeDescr.
An Expression tree can't be compiled unless all reachable Expression nodes
are resolved to concrete types, i.e. type inference has completed successfully.

View file

@ -0,0 +1,21 @@
/** @file type_ref.hpp **/
#pragma once
namespace xo {
namespace scm {
using type_var = xo::flatstring<11>;
/** @class type_ref
* @brief name and eventual resolution for type associated with an expression.
*
*
**/
struct type_ref {
};
} /*namespace scm*/
} /*namespace xo*/
/** end type_ref.hpp **/

53
xo-reader/README Normal file
View file

@ -0,0 +1,53 @@
1. in parser we need.. type unification?
2. or perhaps just need to introduce type variables.
3. we can't resolve type for a recursive pair of functions until we've seen both of them..
tho we could require letrec
def foo = lambda (n : i64) { let (n == 0) then 1 else n * foo(n - 1); };
strategy:
----------
while parsing def, instead of creating DefineExpr with nullptr TypeDescr:
a. create DefineExpr with TypeVariable.
(We have to do this because can't tell nullptr's apart,..)
- generalize xo::reflect::TypeDescrBase
// compose these into Expressions.
//
struct TypeTemplateRef {
bool is_concrete() const { return td_ && td_->is_concrete(); }
// generated name, so we can map between types. Don't want to create TypeDescr
// every time we have a typed location. there'd be a lot of them, and hard to collect
flatstring<11> id_;
// if TypeDescr is concrete (fully described), this describes it
TypeDescr td_;
};
// what we know about a type
//
struct TypeTemplate : public Refcounted {
static bool equal(bp<TypeTemplate> lhs, bp<TypeTemplate> rhs);
TypeTemplateRef ref_;
// additional descriptive info...
};
// effectively these are constraints?
//
using TypeSubstitutionMap = map<string, rp<TypeTemplate>>;
will have typeunifier in parserstatemachine
struct TypeUnifier {
// extend as unification proceeds
//
TypeSubstitutionMap substitutions_;
};
alt strategy
-------------