Skip to content

Commit

Permalink
Add better submodule instance pretty-print, prepare for type inference
Browse files Browse the repository at this point in the history
  • Loading branch information
VonTum committed Nov 19, 2024
1 parent a773179 commit 66f82e4
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 111 deletions.
15 changes: 14 additions & 1 deletion src/dev_aid/lsp/hover_info.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::borrow::Cow;

use crate::prelude::*;
use crate::to_string::pretty_print_concrete_instance;

use lsp_types::{LanguageString, MarkedString};

Expand Down Expand Up @@ -71,6 +72,17 @@ impl<'l> HoverCollector<'l> {
}
});
}

fn gather_submodule_hover_infos(&mut self, md: &Module, submodule: &Module, id: FlatID) {
md.instantiations.for_each_instance(|_template_args, inst| {
for (_id, sm) in &inst.submodules {
if sm.original_instruction != id {
continue;
}
self.sus_code(pretty_print_concrete_instance(&submodule.link_info, &sm.template_args, &self.linker.types));
}
});
}
}

pub fn hover(info: LocationInfo, linker: &Linker, file_data: &FileData) -> Vec<MarkedString> {
Expand Down Expand Up @@ -124,7 +136,7 @@ pub fn hover(info: LocationInfo, linker: &Linker, file_data: &FileData) -> Vec<M

hover.gather_hover_infos(md, decl_id, decl.identifier_type.is_generative());
}
LocationInfo::InModule(_, md, _, InModule::NamedSubmodule(submod)) => {
LocationInfo::InModule(_, md, id, InModule::NamedSubmodule(submod)) => {
let submodule = &linker.modules[submod.module_ref.id];

// Declaration's documentation
Expand All @@ -151,6 +163,7 @@ pub fn hover(info: LocationInfo, linker: &Linker, file_data: &FileData) -> Vec<M

// Module documentation
hover.documentation_link_info(&submodule.link_info);
hover.gather_submodule_hover_infos(md, submodule, id);
}
LocationInfo::InModule(_md_id, md, id, InModule::Temporary(wire)) => {
let mut details_vec: Vec<Cow<str>> = Vec::with_capacity(2);
Expand Down
1 change: 0 additions & 1 deletion src/dev_aid/lsp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,6 @@ pub fn lsp_main() -> Result<(), Box<dyn Error + Sync + Send>> {

// Create the transport. Includes the stdio (stdin and stdout) versions but this could
// also be implemented to use sockets or HTTP.
//let (connection, io_threads) = Connection::listen(SocketAddr::from(([127,0,0,1], 25000)))?;
println!("Connecting on port {}...", config().lsp_port);
let (connection, io_threads) =
lsp_server::Connection::connect(SocketAddr::from(([127, 0, 0, 1], config().lsp_port)))?;
Expand Down
32 changes: 19 additions & 13 deletions src/instantiation/concrete_typecheck.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
use crate::typing::{concrete_type::{ConcreteType, BOOL_CONCRETE_TYPE, INT_CONCRETE_TYPE}, delayed_constraint::{DelayedConstraint, DelayedConstraintStatus, DelayedConstraintsList}, template::check_all_template_args_valid, type_inference::FailedUnification};

use crate::typing::template::ConcreteTemplateArg;
use crate::typing::{
concrete_type::{ConcreteType, BOOL_CONCRETE_TYPE, INT_CONCRETE_TYPE},
delayed_constraint::{DelayedConstraint, DelayedConstraintStatus, DelayedConstraintsList},
type_inference::FailedUnification
};

use super::*;

Expand Down Expand Up @@ -147,14 +153,15 @@ impl DelayedConstraint<InstantiationContext<'_, '_>> for SubmoduleTypecheckConst
let submod_instr = context.md.link_info.instructions[sm.original_instruction].unwrap_submodule();
let sub_module = &context.linker.modules[sm.module_uuid];

if !check_all_template_args_valid(
&context.errors,
submod_instr.module_ref.get_total_span(),
&sub_module.link_info,
&sm.template_args,
) {
return DelayedConstraintStatus::NoProgress;
};
// Check if there's any argument that isn't known
for (_id, arg) in &sm.template_args {
match arg {
ConcreteTemplateArg::NotProvided => {
return DelayedConstraintStatus::NoProgress;
}
ConcreteTemplateArg::Type(..) | ConcreteTemplateArg::Value(..) => {}
}
}

if let Some(instance) = sub_module.instantiations.instantiate(
sub_module,
Expand All @@ -169,7 +176,7 @@ impl DelayedConstraint<InstantiationContext<'_, '_>> for SubmoduleTypecheckConst
(None, Some(connecting_wire)) => {
// Port is not enabled, but attempted to be used
// A question may be "What if no port was in the source code? There would be no error reported"
// But this is okay, because non-visible ports are only possible for function calls
// But this is okay, because nonvisible ports are only possible for function calls
// We have a second routine that reports invalid interfaces.
let source_code_port = &sub_module.ports[port_id];
for span in &connecting_wire.name_refs {
Expand Down Expand Up @@ -249,9 +256,8 @@ impl DelayedConstraint<InstantiationContext<'_, '_>> for SubmoduleTypecheckConst
let submod_instr = context.md.link_info.instructions[sm.original_instruction].unwrap_submodule();
let sub_module = &context.linker.modules[sm.module_uuid];

let name = submod_instr.get_name(sub_module);

let message = format!("Could not fully instantiate {name}!");
let submodule_template_args_string = pretty_print_concrete_instance(&sub_module.link_info, &sm.template_args, &context.linker.types);
let message = format!("Could not fully instantiate {submodule_template_args_string}");

context.errors.error(submod_instr.get_most_relevant_span(), message);
}
Expand Down
10 changes: 6 additions & 4 deletions src/instantiation/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::ops::{Deref, Index, IndexMut};

use crate::linker::{get_builtin_type, IsExtern};
use crate::prelude::*;
use crate::typing::template::GlobalReference;
use crate::typing::template::{GlobalReference, HowDoWeKnowTheTemplateArg};

use num::BigInt;

Expand Down Expand Up @@ -639,11 +639,13 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> {
for (_id, v) in &submodule.module_ref.template_args {
template_args.alloc(match v {
Some(arg) => match &arg.kind {
TemplateArgKind::Type(typ) => {
ConcreteTemplateArg::Type(self.concretize_type(typ)?)
}
TemplateArgKind::Type(typ) => ConcreteTemplateArg::Type(
self.concretize_type(typ)?,
HowDoWeKnowTheTemplateArg::Given
),
TemplateArgKind::Value(v) => ConcreteTemplateArg::Value(
self.generation_state.get_generation_value(*v)?.clone(),
HowDoWeKnowTheTemplateArg::Given
),
},
None => ConcreteTemplateArg::NotProvided,
Expand Down
2 changes: 1 addition & 1 deletion src/instantiation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ fn perform_instantiation(
template_args: &ConcreteTemplateArgs,
) -> InstantiatedModule {
let mut context = InstantiationContext {
name: pretty_print_concrete_instance(linker, &md.link_info, template_args),
name: pretty_print_concrete_instance(&md.link_info, template_args, &linker.types),
generation_state: GenerationState {
md,
generation_state: md.link_info.instructions.map(|(_, _)| SubModuleOrWire::Unnasigned),
Expand Down
54 changes: 26 additions & 28 deletions src/to_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,38 +221,36 @@ impl Module {
}
}

pub fn pretty_print_concrete_instance(
linker: &Linker,
link_info: &LinkInfo,
template_args: &ConcreteTemplateArgs,
) -> String {
assert!(link_info.template_arguments.len() == template_args.len());

let mut result = link_info.get_full_name();

if !link_info.template_arguments.is_empty() {
result.push_str("::<");

for (id, input) in &link_info.template_arguments {
let given_arg = &template_args[id];
pub fn pretty_print_concrete_instance<TypVec>(
target_link_info: &LinkInfo,
given_template_args: &ConcreteTemplateArgs,
linker_types: &TypVec
) -> String
where TypVec: Index<TypeUUID, Output = StructType> {
assert!(given_template_args.len() == target_link_info.template_arguments.len());
let object_full_name = target_link_info.get_full_name();
if given_template_args.len() == 0 {
return format!("{object_full_name} #()");
}

result.push_str(&input.name);
match given_arg {
ConcreteTemplateArg::Type(t) => {
write!(result, " = {}, ", t.to_string(&linker.types)).unwrap();
}
ConcreteTemplateArg::Value(v) => {
write!(result, " = {}, ", v.value).unwrap();
}
ConcreteTemplateArg::NotProvided => {
result.push_str(" not provided, ");
}
use std::fmt::Write;
let mut result = format!("{object_full_name} #(\n");
for (id, arg) in given_template_args {
let arg_in_target = &target_link_info.template_arguments[id];
write!(result, " {}: ", arg_in_target.name).unwrap();
match arg {
ConcreteTemplateArg::Type(concrete_type, how_do_we_know_the_template_arg) => {
write!(result, "type {} /* {} */,\n", concrete_type.to_string(linker_types), how_do_we_know_the_template_arg.to_str()).unwrap();
}
ConcreteTemplateArg::Value(typed_value, how_do_we_know_the_template_arg) => {
write!(result, "{} /* {} */,\n", typed_value.value.to_string(), how_do_we_know_the_template_arg.to_str()).unwrap();
}
ConcreteTemplateArg::NotProvided => {
write!(result, "/* Could not infer */\n").unwrap();
}
}

result.truncate(result.len() - 2);
result.push_str(">");
}

result.push(')');
result
}
61 changes: 20 additions & 41 deletions src/typing/template.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::prelude::*;

use super::{abstract_type::AbstractType, concrete_type::ConcreteType};
use crate::{flattening::WrittenType, linker::LinkInfo, value::TypedValue};
use crate::{flattening::WrittenType, value::TypedValue};

#[derive(Debug)]
pub struct GlobalReference<ID> {
Expand Down Expand Up @@ -92,22 +92,37 @@ impl TemplateArgKind {
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum HowDoWeKnowTheTemplateArg {
Given,
Inferred,
}

impl HowDoWeKnowTheTemplateArg {
pub fn to_str(&self) -> &'static str {
match self {
HowDoWeKnowTheTemplateArg::Given => "given",
HowDoWeKnowTheTemplateArg::Inferred => "inferred",
}
}
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ConcreteTemplateArg {
Type(ConcreteType),
Value(TypedValue),
Type(ConcreteType, HowDoWeKnowTheTemplateArg),
Value(TypedValue, HowDoWeKnowTheTemplateArg),
NotProvided,
}

impl ConcreteTemplateArg {
#[track_caller]
pub fn unwrap_type(&self) -> &ConcreteType {
let Self::Type(t) = self else {unreachable!()};
let Self::Type(t, _) = self else {unreachable!()};
t
}
#[track_caller]
pub fn unwrap_value(&self) -> &TypedValue {
let Self::Value(v) = self else {unreachable!()};
let Self::Value(v, _) = self else {unreachable!()};
v
}
}
Expand All @@ -119,39 +134,3 @@ pub type TemplateArgs = FlatAlloc<Option<TemplateArg>, TemplateIDMarker>;
pub type TemplateAbstractTypes = FlatAlloc<AbstractType, TemplateIDMarker>;
pub type TemplateInputs = FlatAlloc<TemplateInput, TemplateIDMarker>;
pub type ConcreteTemplateArgs = FlatAlloc<ConcreteTemplateArg, TemplateIDMarker>;

pub fn check_all_template_args_valid(
errors: &ErrorCollector,
span: Span,
target_link_info: &LinkInfo,
template_args: &ConcreteTemplateArgs,
) -> bool {
let mut not_found_list: Vec<&TemplateInput> = Vec::new();
for (id, arg) in &target_link_info.template_arguments {
match &template_args[id] {
ConcreteTemplateArg::Type(_) => {}
ConcreteTemplateArg::Value(_) => {}
ConcreteTemplateArg::NotProvided => {
not_found_list.push(arg);
}
}
}
if !not_found_list.is_empty() {
let mut uncovered_ports_list = String::new();
for v in &not_found_list {
use std::fmt::Write;
write!(uncovered_ports_list, "'{}', ", v.name).unwrap();
}
uncovered_ports_list.truncate(uncovered_ports_list.len() - 2); // Cut off last comma
let err_ref = errors.error(span, format!("Could not instantiate {} because the template arguments {uncovered_ports_list} were missing and no default was provided", target_link_info.get_full_name()));
for v in &not_found_list {
err_ref.info(
(v.name_span, target_link_info.file),
format!("'{}' defined here", v.name),
);
}
false
} else {
true
}
}
32 changes: 10 additions & 22 deletions test.sus_errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -621,32 +621,20 @@ Warning: Unused Variable: This variable does not affect the output ports of this
│ ──┬──
│ ╰──── Unused Variable: This variable does not affect the output ports of this module
─────╯
Error: Could not instantiate ::FIFO because the template arguments 'T', 'DEPTH', 'READY_SLACK' were missing and no default was provided
╭─[test.sus:649:2]
649 │ FIFO fiii
│ ──┬─
│ ╰─── Could not instantiate ::FIFO because the template arguments 'T', 'DEPTH', 'READY_SLACK' were missing and no default was provided
├─[/home/lennart/.sus/0.2.0-devel/stl/util.sus:36:2]
36 │ T,
│ ┬
│ ╰── 'T' defined here
37 │ int DEPTH,
│ ──┬──
│ ╰──── 'DEPTH' defined here
39 │ int READY_SLACK
│ ─────┬─────
│ ╰─────── 'READY_SLACK' defined here
─────╯
Error: Could not fully instantiate fiii!
Error: Could not fully instantiate ::FIFO #(
T: /* Could not infer */
DEPTH: /* Could not infer */
READY_SLACK: /* Could not infer */
)
╭─[test.sus:649:7]
649 │ FIFO fiii
│ ──┬─
│ ╰─── Could not fully instantiate fiii!
│ ╰─── Could not fully instantiate ::FIFO #(
T: /* Could not infer */
DEPTH: /* Could not infer */
READY_SLACK: /* Could not infer */
)
─────╯
Error: Pre-emptive error because latency-unspecified 'o' is never written to.
(This is because work-in-progress code would get a lot of latency counting errors while unfinished)
Expand Down

0 comments on commit 66f82e4

Please sign in to comment.