## type-declaration-types.pkg
#
# Datastructures describing type declarations.
#
# In particular,
#
# Type
#
# provides the value type bound by the symbol table
# for that namespace -- see OVERVIEW section in
#
#
src/lib/compiler/front/typer-stuff/symbolmapstack/symbolmapstack.pkg#
# CAVEAT PROGRAMMER: Many types in this file are hardwired in the pickler -- see Note[1].
# Compiled by:
#
src/lib/compiler/front/typer-stuff/typecheckdata.sublibstipulate
package ip = inverse_path; # inverse_path is from
src/lib/compiler/front/typer-stuff/basics/symbol-path.pkg package mp = stamppath; # stamppath is from
src/lib/compiler/front/typer-stuff/modules/stamppath.pkg package ph = picklehash; # picklehash is from
src/lib/compiler/front/basics/map/picklehash.pkg package pl = property_list; # property_list is from
src/lib/src/property-list.pkg package sta = stamp; # stamp is from
src/lib/compiler/front/typer-stuff/basics/stamp.pkg package sy = symbol; # symbol is from
src/lib/compiler/front/basics/map/symbol.pkg package vh = varhome; # varhome is from
src/lib/compiler/front/typer-stuff/basics/varhome.pkg package lnd = line_number_db; # line_number_db is from
src/lib/compiler/front/basics/source/line-number-db.pkgherein
package type_declaration_types
: (weak) Type_Declaration_Types # Type_Declaration_Types is from
src/lib/compiler/front/typer-stuff/types/type-declaration-types.api {
Label = sy::Symbol;
Typescheme_Eqflags # Track which args in a typescheme must be equality types.
=
List( Bool ); # eqflags.
package e { # Give YES/NO/... their own little namespace.
#
Is_Eqtype
= YES
| NO
| INDETERMINATE
# This was "IND", which I'm guessing was a cryptonym for "INDETERMINATE" -- 2009-03-21 CrT
| CHUNK
| DATA
| UNDEF
;
};
Literal_Kind
=
INT
| UNT | FLOAT | CHAR | STRING;
Typevar # User-specified type variables like X.
#
= USER_TYPEVAR {
name: sy::Symbol, # A type variable symbol.
eq: Bool, # Must it resolve to an 'equality type'?
fn_nesting: Int # Outermost fun/fn lexical context mentioning/using us.
}
| META_TYPEVAR
# A typeagnostic ("polymorphic") type variable. It expresses maximal ignorance: This is what we initialize a TYPEVAR_REF to before
{ # doing type inference on it -- see generalize_type' in
src/lib/compiler/front/typer/types/type-core-language-declaration-g.pkg eq: Bool, # Must it resolve to an 'equality type'?
fn_nesting: Int # Outermost fun/fn lexical context mentioning/using us.
# fn_nesting = infinity for META-args
# fn_nesting < infinity for lambda bound
}
| INCOMPLETE_RECORD_TYPEVAR {
# Used to represent a record type before we know all of its fields. For example if we see "foo.bar" we know 'foo' is a record, but the only field we know is 'bar'.
known_fields: List( (Label, Typoid) ),
eq: Bool, # Must it resolve to an 'equality type'?
fn_nesting: Int # Outermost fun/fn lexical context mentioning/using us.
}
| RESOLVED_TYPEVAR Typoid
# When we resolve a META_TYPEVAR to a concrete type, we replace it by this.
| OVERLOADED_TYPEVAR Bool
# arg is TRUE iff it must resolve to an equality type.
# Represents overloaded operators like '+' which must be resolved at compiletime to concrete functions based on types of arguments.
# Overloaded ops are set up in
src/lib/core/init/pervasive.pkg # and compiletime-resolved in
src/lib/compiler/front/typer/types/resolve-overloaded-variables.pkg
| LITERAL_TYPEVAR {
# Literals like '0' may be any of (Int, Unt, Integer, ...). We use this until the type resolves.
kind: Literal_Kind,
source_code_region: lnd::Source_Code_Region
}
| TYPEVAR_MARK Int
also
Typepath
= TYPEPATH_VARIABLE Exception
| TYPEPATH_TYPE Type
| TYPEPATH_GENERIC (List(Typepath), List(Typepath))
| TYPEPATH_APPLY (Typepath, List(Typepath))
| TYPEPATH_SELECT (Typepath, Int)
also
Typekind
= BASE Int # Used for builtin types like Char/String/Float/Exception -- see pt2tc in
src/lib/compiler/front/typer-stuff/types/core-type-types.pkg
| SUMTYPE
{ index: Int,
stamps: Vector( sta::Stamp ),
root: Null_Or( sta::Stamp ), # The root field used by type spec only.
free_types: List( Type ),
family: Sumtype_Family
}
| ABSTRACT Type
# Used in strong sealing; the process starts in the STRONG_PACKAGE_CAST case in type_constrained_package() in
src/lib/compiler/front/typer/main/type-package-language-g.pkg
| FORMAL
# Used only inside apis
| TEMP
# Used only during sumtype elaborations
| FLEXIBLE_TYPE Typepath
# Macro expanded formal type constructor
# Nomenclature: "Definition of SML" calls typcons from apis "flexible" an all others "rigid".
also
Type # Type is the referent for symbolmapstack_entry::Symbolmapstack_Entry.NAMED_TYPE
= SUM_TYPE # Used for raw::SUM_TYPE (==sumtypes) -- see type_sumtype_declaration in
src/lib/compiler/front/typer/main/type-type.pkg Sumtype_Record #
| NAMED_TYPE {
# Used for raw::NAMED_TYPE (not sumtypes) -- see typecheck_named_type() in
src/lib/compiler/front/typer/main/type-type.pkg #
stamp: sta::Stamp, # stamp is from
src/lib/compiler/front/typer-stuff/basics/stamp.pkg typescheme: Typescheme, # typescheme.arity gives the formals like 'X';
# # typescheme.body gives the 'THIS
| THAT ...' info.
strict: List( Bool ),
namepath: ip::Inverse_Path # Name is ip::last(path) -- the 'Foo' from Foo = ... or Foo(X) = ...
}
| TYPE_BY_STAMPPATH {
# Used only inside apis
arity: Int,
stamppath: mp::Stamppath, # stamppath is from
src/lib/compiler/front/typer-stuff/modules/stamppath.pkg namepath: ip::Inverse_Path # Name is ip::last(path) -- the 'Foo' from Foo = ...
}
| RECORD_TYPE List( Label )
| RECURSIVE_TYPE Int
# Used only in domain type of Valcon_Info
| FREE_TYPE Int
# Used only in domain type of Valcon_Info
| ERRONEOUS_TYPE
also
Typoid # Things which are type-like but not actually types, hence the name "typoid".
= TYPEVAR_REF Typevar_Ref
| TYPESCHEME_ARG Int
# i-th argument to a typescheme.
| WILDCARD_TYPOID
| UNDEFINED_TYPOID
| TYPCON_TYPOID (Type, List(Typoid))
| TYPESCHEME_TYPOID
# A type with typevars: Foo(X) = ...
{ typescheme: Typescheme,
typescheme_eqflags: Typescheme_Eqflags # Track which typescheme args are equality types.
}
also
Typescheme # Represents a type with typevars: Foo(X) = ...
= TYPESCHEME
{ arity: Int,
body: Typoid
}
withtype
Typevar_Ref
=
{ ref_typevar: Ref( Typevar ),
id: Int # Purely for debuggging printout purposes.
}
also
Valcon_Info # Used in Sumtype_Member
=
{ name: sy::Symbol,
form: vh::Valcon_Form, # Runtime form for valcon: tagged_int, exception , ...
domain: Null_Or( Typoid )
}
also
Sumtype_Member # A member of a family of (potentially) mutually recursive sumtypes.
= # Might be only one member in the family.
{ name_symbol: sy::Symbol,
arity: Int,
is_eqtype: Ref( e::Is_Eqtype ), # Records whether this is/isn't/might-be/... an "equality type".
is_lazy: Bool,
valcons: List( Valcon_Info ),
an_api: vh::Valcon_Signature
}
also
Sumtype_Family
=
{ mkey: sta::Stamp, # "member key"...?
members: Vector( Sumtype_Member ),
property_list: pl::Property_List
}
also
Stub_Info
=
{ owner: ph::Picklehash,
is_lib: Bool
}
also
Sumtype_Record # Sumtype_Record is the referent for stammapstack::Stampmapstack.type_map, module_level_declarations::Modtree.SUMTYPE_MODTREE_NODE
=
{ stamp: sta::Stamp,
arity: Int,
is_eqtype: Ref( e::Is_Eqtype ), # YES/NO/... Records what we know about legality of equality comparisons on this type.
#
kind: Typekind,
namepath: ip::Inverse_Path, # Name is ip::last(path) -- the 'Foo' from Foo = ...
stub: Null_Or( Stub_Info )
};
debugging = typer_data_controls::types_debugging; # REF FALSE
stipulate
#
next_type_var_id = REF 0; # Used purely for debugging printout purposes.
#
herein
#
fun allocate_typevar_id ()
=
{ id = *next_type_var_id;
next_type_var_id := id + 1;
id;
};
fun make_typevar_ref
( typevar: Typevar,
stack: List(String)
)
:
Typevar_Ref
=
{ if *debugging
printf "make_typevar_ref making typevar_ref id%d for %s\n" *next_type_var_id (string::join "" (reverse stack));
fi;
#
{ ref_typevar => REF typevar,
id => allocate_typevar_id()
};
};
fun make_typevar_ref'
( ref_typevar: Ref( Typevar ),
stack: List(String)
)
:
Typevar_Ref
=
{ if *debugging
printf "make_typevar_ref' making typevar_ref id%d for %s\n" *next_type_var_id (string::join "" (reverse stack));
fi;
#
{ id => allocate_typevar_id (),
ref_typevar
};
};
end;
fun copy_typevar_ref ({ ref_typevar, ... }: Typevar_Ref)
=
{ ref_typevar => REF *ref_typevar,
id => allocate_typevar_id()
};
infinity = 10000000; # Now you know. :)
Valcon # Valcon" == "Value Constructor" -- "FOO' in "Foo = FOO".
= # CAVEAT PROGRAMMER: This record is hardwired in the pickler -- see Note[1]
VALCON { # The first three fields are the only ones that really matter:
name: sy::Symbol, # Name of valcon -- "FOO" value-symbol.
typoid: Typoid,
form: vh::Valcon_Form, # Runtime form for valcon: tagged_int, exception , ...
#
is_constant: Bool, # TRUE iff constructor takes no arguments -- e.g., TRUE, FALSE, NULL. (This field is redundant, could be determined from type.)
signature: vh::Valcon_Signature, # (Redundant, could be determined from type.)
#
is_lazy: Bool # Does valcon belong to lazy sumtype? (Nonstandard, undocumented extension.)
};
}; # package types
end; # stipulate
##########################################################################
# Note[1]
# Various types in this file are hardwired in the pickling code:
#
#
src/lib/compiler/src/library/pickler.pkg#
src/lib/compiler/src/library/unpickler.pkg#
#
src/lib/compiler/front/semantic/pickle/unpickler-junk.pkg#
src/lib/compiler/front/semantic/pickle/pickler-junk.pkg#
# Modifying these types is nontrivial because pickled code is on
# disk and mixing the old and new pickled versions won't work.
#
# Modify these types will require doing a two-step dance:
# 1) Define a replacement type for an existing type.
# 2) Modify all relevant code to accept the new type as well as the old type.
# 3) Do a full compile cycle to establish the new code.
# 3) Convert all code to generate the new type instead of the old type.
# 4) Do a full compile cycle to flush out all pickles containing the original type.
# 5) Remove the original type and the code using it.
# 6) Do a full compile cycle to flush out all remnants of the original type.