Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Definition file improvements #185

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions checker/examples/run_checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ fn main() {
None,
);

if args.iter().any(|arg| arg == "--emit-dts") && !result.diagnostics.has_error() {
eprintln!("dts:");
let mut buf = String::new();
synthesis::definition_files::build_definition_file(&result, &mut buf);
eprintln!("{buf}");
}

if args.iter().any(|arg| arg == "--types") {
eprintln!("Types:");
let types = result.types.into_vec_temp();
Expand Down
7 changes: 3 additions & 4 deletions checker/src/context/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,12 @@ impl RootContext {
}
}

pub fn new_module_context<'a, T: crate::ReadFromFS, A: crate::ASTImplementation>(
pub fn synthesise_module<T: crate::ReadFromFS, A: crate::ASTImplementation>(
&self,
source: SourceId,
module: A::Module<'static>,
checking_data: &'a mut CheckingData<T, A>,
) -> &'a SynthesisedModule<A::OwnedModule> {
checking_data: &mut CheckingData<T, A>,
) {
let module_scope = crate::Scope::Module { source, exported: Exported::default() };
let mut environment = self.new_lexical_environment(module_scope);
A::synthesise_module(&module, source, &mut environment, checking_data);
Expand All @@ -138,7 +138,6 @@ impl RootContext {

// TODO better way to do this?
checking_data.modules.synthesised_modules.insert(source, module);
checking_data.modules.synthesised_modules.get(&source).unwrap()
}

/// TODO working things out:
Expand Down
67 changes: 64 additions & 3 deletions checker/src/features/modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,65 @@ impl Exported {
pub fn keys(&self) -> impl Iterator<Item = &str> {
self.named.keys().chain(self.named_types.keys()).map(AsRef::as_ref)
}

/// For tree shaking
pub(crate) fn evaluate_generally(
&self,
root: &crate::RootContext,
types: &mut crate::types::TypeStore,
) {
use crate::context::invocation::InvocationContext;
use crate::source_map::{Nullable, SpanWithSource};
use crate::types::{
calling::{CallingInput, SynthesisedArgument},
SpecialObject, Type,
};

// TODO might need special
let mut environment = root.new_lexical_environment(Scope::Block {});

if let Some(default) = &self.default {
match types.get_type_by_id(*default) {
Type::SpecialObject(SpecialObject::Function(func, this_value)) => {
let func = types.get_function_from_id(*func);
let mut arguments = Vec::new();
for parameter in &func.parameters.parameters {
arguments.push(SynthesisedArgument {
// TODO get_constraint + open
value: parameter.ty,
spread: false,
position: SpanWithSource::NULL,
});
}
let input = CallingInput {
called_with_new: crate::types::calling::CalledWithNew::None,
call_site: SpanWithSource::NULL,
max_inline: 0,
};

let this_value = *this_value;
let _result = func.clone().call(
(this_value, &arguments, None, None),
input,
&mut environment,
(&mut InvocationContext::new_empty(), &mut Default::default()),
types,
);

crate::utilities::notify!("Call result as well");
}
Type::Object(_d) => {
todo!()
}
ty => {
crate::utilities::notify!("Cannot call {:?}", ty);
}
}
}
for (_name, (_variable_id, _)) in self.named.iter() {
todo!("call like type")
}
}
}

/// After a syntax error
Expand Down Expand Up @@ -351,9 +410,11 @@ pub fn import_file<T: crate::ReadFromFS, A: crate::ASTImplementation>(
match module {
Ok(module) => {
let root = &environment.get_root();
let new_module_context =
root.new_module_context(source, module, checking_data);
Some(Ok(new_module_context))
root.synthesise_module(source, module, checking_data);

let module =
checking_data.modules.synthesised_modules.get(&source).unwrap();
Some(Ok(module))
}
Err(err) => Some(Err(err)),
}
Expand Down
9 changes: 8 additions & 1 deletion checker/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,10 +509,17 @@ pub fn check_project<T: crate::ReadFromFS, A: crate::ASTImplementation>(
let current = checking_data.options.measure_time.then(std::time::Instant::now);
match module {
Ok(module) => {
let _module = root.new_module_context(source, module, &mut checking_data);
root.synthesise_module(source, module, &mut checking_data);
if let Some(current) = current {
checking_data.chronometer.check += current.elapsed();
}

let evaluate_exports = checking_data.options.evaluate_exports;
if evaluate_exports {
let module =
checking_data.modules.synthesised_modules.get(&source).unwrap();
module.exported.clone().evaluate_generally(&root, &mut checking_data.types);
}
}
Err(err) => {
checking_data.diagnostics_container.add_error(err);
Expand Down
104 changes: 104 additions & 0 deletions checker/src/synthesis/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,107 @@ pub mod interactive {
}
}
}

pub mod definition_files {
use iterator_endiate::EndiateIteratorExt;
use parser::ExpressionOrStatementPosition;

use crate::{
types::{printing, GenericChain},
FunctionId,
};

pub fn build_definition_file(result: &crate::CheckOutput<super::EznoParser>, buf: &mut String) {
for (source_id, module) in &result.modules {
for item in &module.content.items {
match item {
parser::StatementOrDeclaration::Declaration(parser::Declaration::Export(
decorated,
)) => match &decorated.on {
parser::ast::ExportDeclaration::Variable { exported, position: _ } => {
match exported {
parser::ast::export::Exportable::Class(_) => todo!(),
parser::ast::export::Exportable::Function(func) => {
let expected = result.types.get_function_from_id(FunctionId(
*source_id,
parser::ASTNode::get_position(func).start,
));
buf.push_str("export function ");
buf.push_str(func.name.as_option_str().unwrap_or_default());
buf.push('(');
for (not_at_end, param) in
expected.parameters.parameters.iter().nendiate()
{
buf.push_str(&param.name);
buf.push_str(": ");
printing::print_type_into_buf(
param.ty,
buf,
&mut Default::default(),
GenericChain::None,
&result.types,
&module.info,
false,
);
if not_at_end {
buf.push_str(", ");
}
}
buf.push(')');
buf.push_str(": ");
printing::print_type_into_buf(
expected.return_type,
buf,
&mut Default::default(),
GenericChain::None,
&result.types,
&module.info,
false,
);
buf.push_str(";\n");
}
parser::ast::export::Exportable::Variable(_) => todo!(),
parser::ast::export::Exportable::Interface(item) => {
buf.push_str("export ");
todo!("{item:?}");
// item.to_string_from_buffer(buf, &ToStringOptions::typescript(), LocalToStringInformation { under: })
}
parser::ast::export::Exportable::TypeAlias(item) => {
buf.push_str("export ");
todo!("{item:?}");
// item.to_string_from_buffer(buf, &ToStringOptions::typescript(), LocalToStringInformation { under: })
}
parser::ast::export::Exportable::Parts(_) => todo!(),
parser::ast::export::Exportable::ImportAll { .. } => {
todo!()
}
parser::ast::export::Exportable::ImportParts { .. } => todo!(),
}
}
parser::ast::ExportDeclaration::Default { .. } => todo!(),
parser::ast::ExportDeclaration::DefaultFunction { .. } => todo!(),
},
parser::StatementOrDeclaration::Declaration(
parser::Declaration::Interface(_),
) => {
todo!()
}
parser::StatementOrDeclaration::Declaration(
parser::Declaration::TypeAlias(_),
) => {
todo!()
}
parser::StatementOrDeclaration::Declaration(
parser::Declaration::DeclareVariable(..),
) => {}
parser::StatementOrDeclaration::Declaration(parser::Declaration::Class(..)) => {
}
parser::StatementOrDeclaration::Statement(
parser::Statement::MultiLineComment(..),
) => {}
_ => {}
}
}
}
}
}
Loading