Skip to content

Commit

Permalink
Add some boilerplate to prepare for type factories resolving types us…
Browse files Browse the repository at this point in the history
…ing the vm.
  • Loading branch information
Ivorforce committed Jul 19, 2024
1 parent 20cba68 commit aec09fe
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 44 deletions.
4 changes: 2 additions & 2 deletions src/resolver/conformance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub struct UnresolvedFunctionImplementation<'a> {
}

pub struct ConformanceResolver<'a, 'b> {
pub runtime: &'b Runtime,
pub runtime: &'b mut Runtime,
pub functions: Vec<UnresolvedFunctionImplementation<'a>>,
}

Expand All @@ -31,7 +31,7 @@ impl <'a, 'b> ConformanceResolver<'a, 'b> {
// TODO For simplicity's sake, we should match the generics IDs of all conformances
// to the ID of the parent abstract function. That way, we can avoid another
// generic to generic mapping later.
let function_head = resolve_function_interface(&syntax.interface, &scope, None, &self.runtime, requirements, generics)?;
let function_head = resolve_function_interface(&syntax.interface, &scope, None, &mut self.runtime, requirements, generics)?;

self.functions.push(UnresolvedFunctionImplementation {
function: function_head,
Expand Down
6 changes: 3 additions & 3 deletions src/resolver/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::resolver::type_factory::TypeFactory;
pub fn resolve_function_body(head: &Rc<FunctionHead>, body: &ast::Expression, scope: &scopes::Scope, runtime: &mut Runtime) -> RResult<Box<FunctionImplementation>> {
let mut builder = ImperativeBuilder {
runtime,
type_factory: TypeFactory::new(scope, &runtime.source),
type_factory: TypeFactory::new(scope),
types: Box::new(TypeForest::new()),
expression_tree: Box::new(ExpressionTree::new(Uuid::new_v4())),
locals_names: Default::default(),
Expand Down Expand Up @@ -68,8 +68,8 @@ pub fn resolve_anonymous_expression(interface: &Rc<FunctionInterface>, body: &as
// 1) We have no parameters
// 2) We have no requirements
let mut builder = ImperativeBuilder {
runtime: &runtime,
type_factory: TypeFactory::new(scope, &runtime.source),
runtime,
type_factory: TypeFactory::new(scope),
types: Box::new(TypeForest::new()),
expression_tree: Box::new(ExpressionTree::new(Uuid::new_v4())),
locals_names: Default::default(),
Expand Down
12 changes: 6 additions & 6 deletions src/resolver/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ impl <'a> GlobalResolver<'a> {
match &pstatement.value.value {
ast::Statement::FunctionDeclaration(syntax) => {
let scope = &self.global_variables;
let function_head = resolve_function_interface(&syntax.interface, &scope, Some(&mut self.module), &self.runtime, &Default::default(), &Default::default())?;
let function_head = resolve_function_interface(&syntax.interface, &scope, Some(&mut self.module), &mut self.runtime, &Default::default(), &Default::default())?;

for decoration in pstatement.decorations_as_vec()? {
let pattern = try_parse_pattern(decoration, Rc::clone(&function_head), &self.global_variables)?;
Expand Down Expand Up @@ -107,7 +107,7 @@ impl <'a> GlobalResolver<'a> {
self.runtime.source.trait_references.insert(Rc::clone(&generic_self_self_getter), Rc::clone(&trait_.generics["Self"]));

let mut resolver = TraitResolver {
runtime: &self.runtime,
runtime: &mut self.runtime,
trait_: &mut trait_,
generic_self_type,
};
Expand All @@ -123,9 +123,9 @@ impl <'a> GlobalResolver<'a> {
ast::Statement::Conformance(syntax) => {
pstatement.no_decorations()?;

let mut type_factory = TypeFactory::new(&self.global_variables, &mut self.runtime.source);
let self_type = type_factory.resolve_type(&syntax.declared_for, true)?;
let declared_type = type_factory.resolve_type(&syntax.declared, false)?;
let mut type_factory = TypeFactory::new(&self.global_variables);
let self_type = type_factory.resolve_type(&syntax.declared_for, true, &mut self.runtime)?;
let declared_type = type_factory.resolve_type(&syntax.declared, false, &mut self.runtime)?;
let TypeUnit::Struct(declared) = &declared_type.unit else {
panic!("Somehow, the resolved type wasn't a struct.")
};
Expand Down Expand Up @@ -161,7 +161,7 @@ impl <'a> GlobalResolver<'a> {
scope.overload_function(&self_getter, self_getter.declared_representation.clone())?;
self.runtime.source.trait_references.insert(Rc::clone(&self_getter), self_trait);

let mut resolver = ConformanceResolver { runtime: &self.runtime, functions: vec![], };
let mut resolver = ConformanceResolver { runtime: &mut self.runtime, functions: vec![], };
for statement in syntax.block.statements.iter() {
statement.no_decorations()?;

Expand Down
2 changes: 1 addition & 1 deletion src/resolver/imperative.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ impl <'a> ImperativeResolver<'a> {
}

pub fn hint_type(&mut self, value: GenericAlias, type_declaration: &ast::Expression, scope: &scopes::Scope) -> RResult<()> {
let type_declaration = self.builder.type_factory.resolve_type(&type_declaration,true)?;
let type_declaration = self.builder.type_factory.resolve_type(&type_declaration,true, &mut self.builder.runtime)?;

for (name, generic) in self.builder.type_factory.generics.iter() {
// need a mut scope
Expand Down
8 changes: 4 additions & 4 deletions src/resolver/imperative_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::resolver::type_factory::TypeFactory;

/// Note: This object should not know about the AST.
pub struct ImperativeBuilder<'a> {
pub runtime: &'a Runtime,
pub runtime: &'a mut Runtime,
pub type_factory: TypeFactory<'a>,
pub types: Box<TypeForest>,
pub expression_tree: Box<ExpressionTree>,
Expand Down Expand Up @@ -66,12 +66,12 @@ impl<'a> ImperativeBuilder<'a> {
pub fn add_function_reference(&mut self, overload: &Rc<FunctionOverload>) -> RResult<ExpressionID> {
match overload.functions.iter().exactly_one() {
Ok(function) => {
let getter = &self.runtime.source.fn_getters[function];
let getter = Rc::clone(&self.runtime.source.fn_getters[function]);
let expression_id = self.make_full_expression(
vec![],
&getter.interface.return_type,
&getter.interface.return_type.clone(),
// Call the getter of the function 'object' instead of the function itself.
ExpressionOperation::FunctionCall(FunctionBinding::pure(Rc::clone(getter)))
ExpressionOperation::FunctionCall(FunctionBinding::pure(getter))
)?;

Ok(expression_id)
Expand Down
22 changes: 11 additions & 11 deletions src/resolver/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ use crate::resolver::scopes;
use crate::resolver::type_factory::TypeFactory;
use crate::util::position::Positioned;

pub fn resolve_function_interface(interface: &ast::FunctionInterface, scope: &scopes::Scope, module: Option<&mut Module>, runtime: &Runtime, requirements: &HashSet<Rc<TraitBinding>>, generics: &HashSet<Rc<Trait>>) -> RResult<Rc<FunctionHead>> {
let mut type_factory = TypeFactory::new(scope, &runtime.source);
pub fn resolve_function_interface(interface: &ast::FunctionInterface, scope: &scopes::Scope, module: Option<&mut Module>, runtime: &mut Runtime, requirements: &HashSet<Rc<TraitBinding>>, generics: &HashSet<Rc<Trait>>) -> RResult<Rc<FunctionHead>> {
let mut type_factory = TypeFactory::new(scope);

let parsed = expressions::parse(&interface.expression, &scope.grammar)?;

Expand All @@ -36,7 +36,7 @@ pub fn resolve_function_interface(interface: &ast::FunctionInterface, scope: &sc
name: identifier.to_string(),
target_type: FunctionTargetType::Global,
call_explicity: FunctionCallExplicity::Implicit,
}, [].into_iter(), &interface.return_type, type_factory, requirements, generics)
}, [].into_iter(), &interface.return_type, type_factory, requirements, generics, runtime)
}
expressions::Value::MemberAccess(target, member) => {
// Member constant like
Expand All @@ -45,7 +45,7 @@ pub fn resolve_function_interface(interface: &ast::FunctionInterface, scope: &sc
name: member.to_string(),
target_type: FunctionTargetType::Member,
call_explicity: FunctionCallExplicity::Implicit,
}, Some(target).into_iter(), &interface.return_type, type_factory, requirements, generics)
}, Some(target).into_iter(), &interface.return_type, type_factory, requirements, generics, runtime)
}
expressions::Value::FunctionCall(target, call_struct) => {
match &target.value {
Expand All @@ -55,7 +55,7 @@ pub fn resolve_function_interface(interface: &ast::FunctionInterface, scope: &sc
name: identifier.to_string(),
target_type: FunctionTargetType::Global,
call_explicity: FunctionCallExplicity::Explicit,
}, call_struct.arguments.iter().map(|a| &a.value), &interface.return_type, type_factory, requirements, generics)
}, call_struct.arguments.iter().map(|a| &a.value), &interface.return_type, type_factory, requirements, generics, runtime)
}
expressions::Value::MemberAccess(target, member) => {
// Member function like
Expand All @@ -64,7 +64,7 @@ pub fn resolve_function_interface(interface: &ast::FunctionInterface, scope: &sc
name: member.to_string(),
target_type: FunctionTargetType::Member,
call_explicity: FunctionCallExplicity::Explicit,
}, Some(target).into_iter().chain(call_struct.arguments.iter().map(|a| &a.value)), &interface.return_type, type_factory, requirements, generics)
}, Some(target).into_iter().chain(call_struct.arguments.iter().map(|a| &a.value)), &interface.return_type, type_factory, requirements, generics, runtime)
}
_ => return Err(RuntimeError::error("Invalid function definition.").to_array()),
}
Expand Down Expand Up @@ -113,13 +113,13 @@ fn resolve_macro_function_interface(module: Option<&mut Module>, runtime: &Runti
}
}

pub fn _resolve_function_interface<'a>(representation: FunctionRepresentation, parameters: impl Iterator<Item=&'a ast::StructArgument>, return_type: &Option<ast::Expression>, mut type_factory: TypeFactory, requirements: &HashSet<Rc<TraitBinding>>, generics: &HashSet<Rc<Trait>>) -> RResult<Rc<FunctionHead>> {
pub fn _resolve_function_interface<'a>(representation: FunctionRepresentation, parameters: impl Iterator<Item=&'a ast::StructArgument>, return_type: &Option<ast::Expression>, mut type_factory: TypeFactory, requirements: &HashSet<Rc<TraitBinding>>, generics: &HashSet<Rc<Trait>>, runtime: &mut Runtime) -> RResult<Rc<FunctionHead>> {
let return_type = return_type.as_ref()
.try_map(|x| type_factory.resolve_type(&x, true))?
.try_map(|x| type_factory.resolve_type(&x, true, runtime))?
.unwrap_or(TypeProto::void());

let (parameters, internal_parameter_names) = parameters
.map(|p| resolve_function_parameter(p, &mut type_factory))
.map(|p| resolve_function_parameter(p, &mut type_factory, runtime))
.process_results(|i| i.unzip())?;

let mut generics = generics.clone();
Expand All @@ -144,7 +144,7 @@ pub fn _resolve_function_interface<'a>(representation: FunctionRepresentation, p
))
}

pub fn resolve_function_parameter(parameter: &ast::StructArgument, type_factory: &mut TypeFactory) -> RResult<(Parameter, String)> {
pub fn resolve_function_parameter(parameter: &ast::StructArgument, type_factory: &mut TypeFactory, runtime: &mut Runtime) -> RResult<(Parameter, String)> {
let Some(type_declaration) = &parameter.type_declaration else {
return Err(
RuntimeError::error("Parameters must have a type.").to_array()
Expand All @@ -161,7 +161,7 @@ pub fn resolve_function_parameter(parameter: &ast::StructArgument, type_factory:

Ok((Parameter {
external_key: parameter.key.clone(),
type_: type_factory.resolve_type(type_declaration, true)?,
type_: type_factory.resolve_type(type_declaration, true, runtime)?,
}, internal_name.clone()))
}

Expand Down
8 changes: 4 additions & 4 deletions src/resolver/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::resolver::interface::resolve_function_interface;
use crate::resolver::type_factory::TypeFactory;

pub struct TraitResolver<'a> {
pub runtime: &'a Runtime,
pub runtime: &'a mut Runtime,
pub trait_: &'a mut Trait,
pub generic_self_type: Rc<TypeProto>,
}
Expand All @@ -27,7 +27,7 @@ impl <'a> TraitResolver<'a> {
match statement {
ast::Statement::FunctionDeclaration(syntax) => {
// TODO What do we do with the parameter names? They don't belong in the interface. Probably the runtime source?
let function_head = resolve_function_interface(&syntax.interface, &scope, None, &self.runtime, requirements, generics)?;
let function_head = resolve_function_interface(&syntax.interface, &scope, None, &mut self.runtime, requirements, generics)?;
if !syntax.body.is_none() {
return Err(
RuntimeError::error(format!("Abstract function {:?} cannot have a body.", function_head).as_str()).to_array()
Expand All @@ -54,9 +54,9 @@ impl <'a> TraitResolver<'a> {
);
};

let mut type_factory = TypeFactory::new(scope, &self.runtime.source);
let mut type_factory = TypeFactory::new(scope);

let variable_type = type_factory.resolve_type(type_declaration, true)?;
let variable_type = type_factory.resolve_type(type_declaration, true, &mut self.runtime)?;

if TypeProto::contains_generics([&variable_type].into_iter()) {
return Err(
Expand Down
40 changes: 27 additions & 13 deletions src/resolver/type_factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ use std::collections::{HashMap, HashSet};
use std::rc::Rc;

use itertools::Itertools;

use uuid::Uuid;
use crate::ast;
use crate::error::{ErrInRange, RResult, RuntimeError};
use crate::parser::expressions;
use crate::program::functions::FunctionTargetType;
use crate::interpreter::runtime::Runtime;
use crate::parser::{expressions, parse_expression};
use crate::program::functions::{FunctionInterface, FunctionTargetType};
use crate::program::traits::{Trait, TraitBinding};
use crate::program::types::{TypeProto, TypeUnit};
use crate::resolver::scopes;
use crate::source::Source;

pub struct TypeFactory<'a> {
pub source: &'a Source,
pub scope: &'a scopes::Scope<'a>,

pub generics: HashMap<String, Rc<Trait>>,
Expand All @@ -23,22 +23,21 @@ pub struct TypeFactory<'a> {
// TODO Essentially this is a form of mini interpreter.
// In the future it might be easier to rewrite it as such.
impl <'a> TypeFactory<'a> {
pub fn new(scope: &'a scopes::Scope<'a>, source: &'a Source) -> TypeFactory<'a> {
pub fn new(scope: &'a scopes::Scope<'a>) -> TypeFactory<'a> {
TypeFactory {
scope,
generics: HashMap::new(),
requirements: HashSet::new(),
source,
}
}

pub fn resolve_trait(&mut self, name: &str) -> RResult<Rc<Trait>> {
pub fn resolve_trait(&mut self, name: &str, runtime: &mut Runtime) -> RResult<Rc<Trait>> {
let reference = self.scope.resolve(FunctionTargetType::Global, &name)?;
let overload = reference.as_function_overload()?;

let function = overload.functions.iter().exactly_one()
.map_err(|_| RuntimeError::error("Function overload cannot be resolved to a type.").to_array())?;
let trait_ = self.source.trait_references.get(function)
let trait_ = runtime.source.trait_references.get(function)
.ok_or_else(|| RuntimeError::error(format!("Interpreted types aren't supported yet; please use an explicit type for now.\n{}", name).as_str()).to_array())?;

return Ok(Rc::clone(trait_))
Expand All @@ -54,7 +53,7 @@ impl <'a> TypeFactory<'a> {
self.requirements.insert(requirement);
}

pub fn resolve_type(&mut self, syntax: &ast::Expression, allow_anonymous_generics: bool) -> RResult<Rc<TypeProto>> {
pub fn resolve_type(&mut self, syntax: &ast::Expression, allow_anonymous_generics: bool, runtime: &mut Runtime) -> RResult<Rc<TypeProto>> {
syntax.no_errors()?;

let parsed = expressions::parse(syntax, &self.scope.grammar)?;
Expand All @@ -63,11 +62,26 @@ impl <'a> TypeFactory<'a> {
return Err(RuntimeError::error("Interpreted types aren't supported yet; please use an explicit type for now.").in_range(parsed.position).to_array())
};

self.resolve_type_by_name(allow_anonymous_generics, &identifier)
// let (expression, _) = parse_expression(identifier)?;
// // TODO We don't actually want to merge into Metatype<String>, we want an instance of
// let result = runtime.evaluate_anonymous_expression(
// &expression,
// FunctionInterface::new_provider(
// &TypeProto::one_arg(&runtime.Metatype, TypeProto::unit_struct(&runtime.traits.as_ref().unwrap().String)),
// vec![]
// ),
// )?;
//
// unsafe {
// let uuid = *(result.ptr as *mut Uuid);
// return Ok(TypeProto::unit_struct(&runtime.source.trait_heads[&uuid]));
// }

self.resolve_type_by_name(allow_anonymous_generics, &identifier, runtime)
.err_in_range(&parsed.position)
}

fn resolve_type_by_name(&mut self, allow_anonymous_generics: bool, type_name: &str) -> RResult<Rc<TypeProto>> {
fn resolve_type_by_name(&mut self, allow_anonymous_generics: bool, type_name: &str, runtime: &mut Runtime) -> RResult<Rc<TypeProto>> {
let arguments = vec![];

if let Some(type_) = self.generics.get(type_name) {
Expand All @@ -76,7 +90,7 @@ impl <'a> TypeFactory<'a> {

if !allow_anonymous_generics || !(type_name.starts_with("#") || type_name.starts_with("$")) {
// No special generic; let's try just resolving it normally.
let trait_ = self.resolve_trait(type_name)?;
let trait_ = self.resolve_trait(type_name, runtime)?;
// Found a trait! Until we actually interpret the expression, this is guaranteed to be unbound.
return Ok(TypeProto::unit_struct(&trait_));
}
Expand All @@ -92,7 +106,7 @@ impl <'a> TypeFactory<'a> {
Some(hash_start_index) => { String::from(&type_name[1..hash_start_index]) }
};

let requirement_trait = self.resolve_trait(&type_name)?;
let requirement_trait = self.resolve_trait(&type_name, runtime)?;
self.register_requirement(Rc::new(TraitBinding {
generic_to_type: HashMap::from([(Rc::clone(&requirement_trait.generics["Self"]), type_.clone())]),
trait_: requirement_trait,
Expand Down
4 changes: 4 additions & 0 deletions src/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ pub struct Source {

// Cache of aggregated module_by_name fields for quick reference.

/// For every getter, which trait it provides.
pub trait_heads: HashMap<Uuid, Rc<Trait>>,
/// For referencible functions, the trait for it as an object.
/// For every getter, which trait it provides.
pub trait_references: HashMap<Rc<FunctionHead>, Rc<Trait>>,
/// For referencible functions, the trait for it as an object.
Expand All @@ -32,6 +35,7 @@ impl Source {
pub fn new() -> Source {
Source {
module_by_name: Default::default(),
trait_heads: Default::default(),
trait_references: Default::default(),
function_traits: Default::default(),
struct_by_trait: Default::default(),
Expand Down

0 comments on commit aec09fe

Please sign in to comment.