Skip to content

v3.types

Constants #

const bool_ = Primitive{
	props: .boolean
}
const int_ = Primitive{
	props: .integer
}
const i8_ = Primitive{
	props: .integer
	size:  8
}
const i16_ = Primitive{
	props: .integer
	size:  16
}
const i32_ = Primitive{
	props: .integer
	size:  32
}
const i64_ = Primitive{
	props: .integer
	size:  64
}
const u8_ = Primitive{
	props: .integer | .unsigned
	size:  8
}
const u16_ = Primitive{
	props: .integer | .unsigned
	size:  16
}
const u32_ = Primitive{
	props: .integer | .unsigned
	size:  32
}
const u64_ = Primitive{
	props: .integer | .unsigned
	size:  64
}
const f32_ = Primitive{
	props: .float
	size:  32
}
const f64_ = Primitive{
	props: .float
	size:  64
}
const string_ = String{}
const char_ = Char{}
const rune_ = Rune{}
const isize_ = ISize{}
const usize_ = USize{}
const void_ = Void{}
const nil_ = Nil{}
const none_ = None{}
const voidptr_ = Pointer{
	base_type: Type(Void{})
}
const charptr_ = Pointer{
	base_type: Type(Char{})
}
const byteptr_ = Pointer{
	base_type: Type(Primitive{
		props: .integer | .unsigned
		size:  8
	})
}

fn builtin_type #

fn builtin_type(name string) ?Type

builtin_type returns the Type for a builtin type name, or none otherwise.

fn builtin_type_value #

fn builtin_type_value(name string) Type

builtin_type_value returns the Type for a known builtin type name.

fn is_builtin_type_name #

fn is_builtin_type_name(name string) bool

is_builtin_type_name reports whether name is one of V's builtin type names.

fn new_scope #

fn new_scope(parent &Scope) &Scope

new_scope returns a reusable type-checker scope with an optional parent.

fn unwrap_pointer #

fn unwrap_pointer(t Type) Type

fn Properties.from #

fn Properties.from[W](input W) !Properties

fn Properties.zero #

fn Properties.zero() Properties

fn TypeChecker.new #

fn TypeChecker.new(a &flat.FlatAst) TypeChecker

fn TypeErrorKind.from #

fn TypeErrorKind.from[W](input W) !TypeErrorKind

type Type #

type Type = Void
	| Unknown
	| Primitive
	| String
	| Char
	| Rune
	| ISize
	| USize
	| Nil
	| None
	| Array
	| ArrayFixed
	| Map
	| Pointer
	| FnType
	| OptionType
	| ResultType
	| Struct
	| Interface
	| Enum
	| SumType
	| Alias
	| MultiReturn

fn (Type) is_pointer #

fn (t Type) is_pointer() bool

fn (Type) is_string #

fn (t Type) is_string() bool

fn (Type) is_integer #

fn (t Type) is_integer() bool

fn (Type) is_float #

fn (t Type) is_float() bool

fn (Type) name #

fn (t Type) name() string

enum Properties #

@[flag]
enum Properties {
	boolean
	float
	integer
	unsigned
	untyped
}

fn (Properties) all #

fn (e &Properties) all(flag_ Properties) bool

fn (Properties) clear #

fn (mut e Properties) clear(flag_ Properties)

fn (Properties) clear_all #

fn (mut e Properties) clear_all()

fn (Properties) has #

fn (e &Properties) has(flag_ Properties) bool

fn (Properties) is_empty #

fn (e &Properties) is_empty() bool

fn (Properties) set #

fn (mut e Properties) set(flag_ Properties)

fn (Properties) set_all #

fn (mut e Properties) set_all()

fn (Properties) toggle #

fn (mut e Properties) toggle(flag_ Properties)

enum TypeErrorKind #

enum TypeErrorKind {
	unknown_ident
	unknown_type
	unknown_fn
	unknown_field
	cannot_index
	if_branch_mismatch
	assignment_mismatch
	return_mismatch
	call_arg_mismatch
	condition_mismatch
	unhandled_node
	unsupported_generic
}

struct Alias #

struct Alias {
pub:
	name      string
	base_type Type
}

struct Array #

struct Array {
pub:
	elem_type Type
}

struct ArrayFixed #

struct ArrayFixed {
pub:
	elem_type Type
	len       int
	len_expr  string
}

struct Char #

struct Char {
	dummy_ u8
}

struct Enum #

struct Enum {
pub:
	name    string
	is_flag bool
}

struct FnType #

struct FnType {
pub:
	params      []Type
	return_type Type
}

struct ISize #

struct ISize {
	dummy_ u8
}

struct Interface #

struct Interface {
pub:
	name string
}

struct Map #

struct Map {
pub:
	key_type   Type
	value_type Type
}

struct MultiReturn #

struct MultiReturn {
pub:
	types []Type
}

struct Nil #

struct Nil {
	dummy_ u8
}

struct None #

struct None {
	dummy_ u8
}

struct OptionType #

struct OptionType {
pub:
	base_type Type
}

struct Pointer #

struct Pointer {
pub:
	base_type Type
}

struct Primitive #

struct Primitive {
pub:
	props Properties
	size  u8
}

struct ResultType #

struct ResultType {
pub:
	base_type Type
}

struct Rune #

struct Rune {
	dummy_ u8
}

struct Scope #

@[heap]
struct Scope {
pub mut:
	parent &Scope = unsafe { nil }
	names  []string
	types  []Type
}

fn (Scope) reset #

fn (mut s Scope) reset(parent &Scope)

reset retargets a pooled scope, clearing its bindings while keeping the backing storage capacity so reuse does not reallocate. Without this clear a pooled scope's arrays accumulate every binding ever inserted across all generations, turning lookup/insert into an O(n) scan over dead entries.

fn (Scope) lookup #

fn (s &Scope) lookup(name string) ?Type

lookup returns the nearest visible type binding for name.

fn (Scope) insert #

fn (mut s Scope) insert(name string, typ Type)

insert records or updates a type binding in this scope.

struct String #

struct String {
	dummy_ u8
}

struct Struct #

struct Struct {
pub:
	name string
}

struct StructField #

struct StructField {
pub:
	name string
	typ  Type
}

struct SumType #

struct SumType {
pub:
	name string
}

struct TypeChecker #

@[heap]
struct TypeChecker {
pub mut:
	a                             &flat.FlatAst = unsafe { nil }
	fn_ret_types                  map[string]Type
	fn_param_types                map[string][]Type
	fn_variadic                   map[string]bool
	structs                       map[string][]StructField
	unions                        map[string]bool
	type_aliases                  map[string]string
	sum_types                     map[string][]string
	enum_names                    map[string]bool
	enum_fields                   map[string][]string
	flag_enums                    map[string]bool
	interface_names               map[string]bool
	interface_fields              map[string][]StructField
	interface_embeds              map[string][]string
	const_types                   map[string]Type
	const_exprs                   map[string]flat.NodeId
	const_modules                 map[string]string
	imports                       map[string]string // alias -> short module name
	file_imports                  map[string]string
	file_modules                  map[string]string
	file_scope                    &Scope = unsafe { nil }
	cur_scope                     &Scope = unsafe { nil }
	scope_pool                    []&Scope
	scope_pool_index              int
	has_builtins                  bool
	cur_module                    string
	cur_file                      string
	errors                        []TypeError
	resolved_call_names           []string // node_id -> resolved function name
	resolved_call_set             []bool
	expr_type_values              []Type // node_id -> complex/contextual resolved type
	expr_type_set                 []bool
	diagnose_unknown_calls        bool
	reject_unlowered_map_mutation bool
	diagnostic_files              map[string]bool
	cur_fn_ret_type               Type = Type(void_)
	smartcasts                    map[string]Type
}

fn (TypeChecker) push_scope #

fn (mut tc TypeChecker) push_scope()

fn (TypeChecker) pop_scope #

fn (mut tc TypeChecker) pop_scope()

fn (TypeChecker) collect #

fn (mut tc TypeChecker) collect(a &flat.FlatAst)

fn (TypeChecker) qualify_fn_name #

fn (tc &TypeChecker) qualify_fn_name(name string) string

fn (TypeChecker) qualify_name #

fn (tc &TypeChecker) qualify_name(name string) string

fn (TypeChecker) annotate_types #

fn (mut tc TypeChecker) annotate_types()

annotate_types performs a scope-aware walk over every function body, tracking local variable types as they are declared, and records complex/contextual expression types. This mirrors what the v2 transformer relies on: the type checker runs BEFORE the transformer and publishes per-expression types, so the transformer can own type-dependent lowering (string ops, in membership, ...) instead of the backend.

It uses a single flat scope per function (an over-approximation: a local stays visible after its block ends), which is harmless for type lookup since variable names are effectively unique within a function.

fn (TypeChecker) expr_type #

fn (tc &TypeChecker) expr_type(id flat.NodeId) ?Type

expr_type returns the resolved type recorded for a node during annotate_types.

fn (TypeChecker) resolved_call_name #

fn (tc &TypeChecker) resolved_call_name(id flat.NodeId) ?string

resolved_call_name returns the checker-resolved function name for a call node.

fn (TypeChecker) register_synth_type #

fn (mut tc TypeChecker) register_synth_type(id flat.NodeId, typ Type)

register_synth_type records the type of a generated or transformed node.

fn (TypeChecker) check_semantics #

fn (mut tc TypeChecker) check_semantics()

fn (TypeChecker) parse_type #

fn (tc &TypeChecker) parse_type(typ string) Type

parse_type converts a V type string (from parser) to a structured Type.

fn (TypeChecker) resolve_type #

fn (tc &TypeChecker) resolve_type(id flat.NodeId) Type

fn (TypeChecker) c_type #

fn (tc &TypeChecker) c_type(t Type) string

struct TypeError #

struct TypeError {
pub:
	msg  string
	kind TypeErrorKind
	node flat.NodeId
}

struct USize #

struct USize {
	dummy_ u8
}

struct Unknown #

struct Unknown {
pub:
	reason string
}

struct Void #

struct Void {
	dummy_ u8
}