chore(els): improve signature help

This commit is contained in:
Shunsuke Shibayama 2023-02-27 03:20:44 +09:00
parent e6b7e65d93
commit 1aa83f140a
26 changed files with 475 additions and 334 deletions

View file

@ -11,7 +11,7 @@ use erg_compiler::hir::Expr;
use lsp_types::{CodeAction, CodeActionKind, CodeActionParams, TextEdit, Url, WorkspaceEdit}; use lsp_types::{CodeAction, CodeActionKind, CodeActionParams, TextEdit, Url, WorkspaceEdit};
use crate::server::{ELSResult, Server}; use crate::server::{send, send_log, ELSResult, Server};
use crate::util; use crate::util;
impl<Checker: BuildRunnable> Server<Checker> { impl<Checker: BuildRunnable> Server<Checker> {
@ -25,11 +25,11 @@ impl<Checker: BuildRunnable> Server<Checker> {
let diag = diags.remove(0); let diag = diags.remove(0);
let mut map = HashMap::new(); let mut map = HashMap::new();
let Some(visitor) = self.get_visitor(&uri) else { let Some(visitor) = self.get_visitor(&uri) else {
Self::send_log("visitor not found")?; send_log("visitor not found")?;
return Ok(None); return Ok(None);
}; };
let Some(artifact) = self.artifacts.get(&uri) else { let Some(artifact) = self.artifacts.get(&uri) else {
Self::send_log("artifact not found")?; send_log("artifact not found")?;
return Ok(None); return Ok(None);
}; };
let warns = artifact let warns = artifact
@ -45,7 +45,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
match visitor.get_min_expr(&token) { match visitor.get_min_expr(&token) {
Some(Expr::Def(def)) => { Some(Expr::Def(def)) => {
let Some(mut range) = util::loc_to_range(def.loc()) else { let Some(mut range) = util::loc_to_range(def.loc()) else {
Self::send_log("range not found")?; send_log("range not found")?;
continue; continue;
}; };
let next = lsp_types::Range { let next = lsp_types::Range {
@ -67,7 +67,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
} }
Some(";") => range.end.character += 1, Some(";") => range.end.character += 1,
Some(other) => { Some(other) => {
Self::send_log(format!("? {other}"))?; send_log(format!("? {other}"))?;
} }
} }
let edit = TextEdit::new(range, "".to_string()); let edit = TextEdit::new(range, "".to_string());
@ -161,7 +161,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
} }
pub(crate) fn send_code_action(&self, msg: &Value) -> ELSResult<()> { pub(crate) fn send_code_action(&self, msg: &Value) -> ELSResult<()> {
Self::send_log(format!("code action requested: {msg}"))?; send_log(format!("code action requested: {msg}"))?;
let params = CodeActionParams::deserialize(&msg["params"])?; let params = CodeActionParams::deserialize(&msg["params"])?;
let result = match params let result = match params
.context .context
@ -172,12 +172,10 @@ impl<Checker: BuildRunnable> Server<Checker> {
Some("quickfix") => self.send_quick_fix(msg, params)?, Some("quickfix") => self.send_quick_fix(msg, params)?,
None => self.send_normal_action(msg, params)?, None => self.send_normal_action(msg, params)?,
Some(other) => { Some(other) => {
Self::send_log(&format!("Unknown code action requested: {other}"))?; send_log(&format!("Unknown code action requested: {other}"))?;
vec![] vec![]
} }
}; };
Self::send( send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }))
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }),
)
} }
} }

View file

@ -7,12 +7,12 @@ use erg_compiler::hir::Expr;
use lsp_types::{CodeLens, CodeLensParams, Url}; use lsp_types::{CodeLens, CodeLensParams, Url};
use crate::server::{ELSResult, Server}; use crate::server::{send, send_log, ELSResult, Server};
use crate::util; use crate::util;
impl<Checker: BuildRunnable> Server<Checker> { impl<Checker: BuildRunnable> Server<Checker> {
pub(crate) fn show_code_lens(&mut self, msg: &Value) -> ELSResult<()> { pub(crate) fn show_code_lens(&mut self, msg: &Value) -> ELSResult<()> {
Self::send_log("code lens requested")?; send_log("code lens requested")?;
let params = CodeLensParams::deserialize(&msg["params"])?; let params = CodeLensParams::deserialize(&msg["params"])?;
let uri = util::normalize_url(params.text_document.uri); let uri = util::normalize_url(params.text_document.uri);
// TODO: parallelize // TODO: parallelize
@ -21,9 +21,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
self.send_class_inherits_lens(&uri)?, self.send_class_inherits_lens(&uri)?,
] ]
.concat(); .concat();
Self::send( send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }))
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }),
)
} }
fn send_trait_impls_lens(&mut self, uri: &Url) -> ELSResult<Vec<CodeLens>> { fn send_trait_impls_lens(&mut self, uri: &Url) -> ELSResult<Vec<CodeLens>> {

View file

@ -9,18 +9,18 @@ use erg_compiler::hir::Expr;
use lsp_types::{ExecuteCommandParams, Location, Url}; use lsp_types::{ExecuteCommandParams, Location, Url};
use crate::server::{ELSResult, Server}; use crate::server::{send, send_log, ELSResult, Server};
use crate::util; use crate::util;
impl<Checker: BuildRunnable> Server<Checker> { impl<Checker: BuildRunnable> Server<Checker> {
pub(crate) fn execute_command(&mut self, msg: &Value) -> ELSResult<()> { pub(crate) fn execute_command(&mut self, msg: &Value) -> ELSResult<()> {
let params = ExecuteCommandParams::deserialize(&msg["params"])?; let params = ExecuteCommandParams::deserialize(&msg["params"])?;
Self::send_log(format!("command requested: {}", params.command))?; send_log(format!("command requested: {}", params.command))?;
#[allow(clippy::match_single_binding)] #[allow(clippy::match_single_binding)]
match &params.command[..] { match &params.command[..] {
other => { other => {
Self::send_log(format!("unknown command: {other}"))?; send_log(format!("unknown command: {other}"))?;
Self::send( send(
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": Value::Null }), &json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": Value::Null }),
) )
} }

View file

@ -17,7 +17,7 @@ use lsp_types::{
MarkupContent, MarkupKind, MarkupContent, MarkupKind,
}; };
use crate::server::{ELSResult, Server}; use crate::server::{send, send_log, ELSResult, Server};
use crate::util; use crate::util;
fn mark_to_string(mark: MarkedString) -> String { fn mark_to_string(mark: MarkedString) -> String {
@ -70,7 +70,7 @@ impl CompletionOrder {
impl<Checker: BuildRunnable> Server<Checker> { impl<Checker: BuildRunnable> Server<Checker> {
pub(crate) fn show_completion(&mut self, msg: &Value) -> ELSResult<()> { pub(crate) fn show_completion(&mut self, msg: &Value) -> ELSResult<()> {
Self::send_log(format!("completion requested: {msg}"))?; send_log(format!("completion requested: {msg}"))?;
let params = CompletionParams::deserialize(&msg["params"])?; let params = CompletionParams::deserialize(&msg["params"])?;
let uri = util::normalize_url(params.text_document_position.text_document.uri); let uri = util::normalize_url(params.text_document_position.text_document.uri);
let path = util::uri_to_path(&uri); let path = util::uri_to_path(&uri);
@ -84,7 +84,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
Some(":") => AccessKind::Attr, // or type ascription Some(":") => AccessKind::Attr, // or type ascription
_ => AccessKind::Name, _ => AccessKind::Name,
}; };
Self::send_log(format!("AccessKind: {acc_kind:?}"))?; send_log(format!("AccessKind: {acc_kind:?}"))?;
let mut result: Vec<CompletionItem> = vec![]; let mut result: Vec<CompletionItem> = vec![];
let contexts = if acc_kind.is_local() { let contexts = if acc_kind.is_local() {
let prev_token = self.file_cache.get_token_relatively(&uri, pos, -1)?; let prev_token = self.file_cache.get_token_relatively(&uri, pos, -1)?;
@ -101,7 +101,6 @@ impl<Checker: BuildRunnable> Server<Checker> {
} else { } else {
self.get_receiver_ctxs(&uri, pos)? self.get_receiver_ctxs(&uri, pos)?
}; };
// Self::send_log(format!("contexts: {:?}", contexts.iter().map(|ctx| &ctx.name).collect::<Vec<_>>())).unwrap();
for (name, vi) in contexts.into_iter().flat_map(|ctx| ctx.dir()) { for (name, vi) in contexts.into_iter().flat_map(|ctx| ctx.dir()) {
if acc_kind.is_attr() && vi.vis.is_private() { if acc_kind.is_attr() && vi.vis.is_private() {
continue; continue;
@ -147,19 +146,17 @@ impl<Checker: BuildRunnable> Server<Checker> {
item.data = Some(Value::String(vi.def_loc.to_string())); item.data = Some(Value::String(vi.def_loc.to_string()));
result.push(item); result.push(item);
} }
Self::send_log(format!("completion items: {}", result.len()))?; send_log(format!("completion items: {}", result.len()))?;
Self::send( send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }))
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }),
)
} }
pub(crate) fn resolve_completion(&self, msg: &Value) -> ELSResult<()> { pub(crate) fn resolve_completion(&self, msg: &Value) -> ELSResult<()> {
Self::send_log(format!("completion resolve requested: {msg}"))?; send_log(format!("completion resolve requested: {msg}"))?;
let mut item = CompletionItem::deserialize(&msg["params"])?; let mut item = CompletionItem::deserialize(&msg["params"])?;
if let Some(data) = &item.data { if let Some(data) = &item.data {
let mut contents = vec![]; let mut contents = vec![];
let Ok(def_loc) = data.as_str().unwrap().parse::<AbsLocation>() else { let Ok(def_loc) = data.as_str().unwrap().parse::<AbsLocation>() else {
return Self::send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": item })); return send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": item }));
}; };
self.show_doc_comment(None, &mut contents, &def_loc)?; self.show_doc_comment(None, &mut contents, &def_loc)?;
let mut contents = contents.into_iter().map(mark_to_string).collect::<Vec<_>>(); let mut contents = contents.into_iter().map(mark_to_string).collect::<Vec<_>>();
@ -169,6 +166,6 @@ impl<Checker: BuildRunnable> Server<Checker> {
value: contents.join("\n"), value: contents.join("\n"),
})); }));
} }
Self::send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": item })) send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": item }))
} }
} }

View file

@ -8,7 +8,7 @@ use erg_compiler::varinfo::VarInfo;
use lsp_types::{GotoDefinitionParams, GotoDefinitionResponse, Url}; use lsp_types::{GotoDefinitionParams, GotoDefinitionResponse, Url};
use crate::server::{ELSResult, Server}; use crate::server::{send, send_log, ELSResult, Server};
use crate::util; use crate::util;
impl<Checker: BuildRunnable> Server<Checker> { impl<Checker: BuildRunnable> Server<Checker> {
@ -18,18 +18,18 @@ impl<Checker: BuildRunnable> Server<Checker> {
token: &Token, token: &Token,
) -> ELSResult<Option<VarInfo>> { ) -> ELSResult<Option<VarInfo>> {
if !token.category_is(TokenCategory::Symbol) { if !token.category_is(TokenCategory::Symbol) {
Self::send_log(format!("not symbol: {token}"))?; send_log(format!("not symbol: {token}"))?;
Ok(None) Ok(None)
} else if let Some(visitor) = self.get_visitor(uri) { } else if let Some(visitor) = self.get_visitor(uri) {
Ok(visitor.get_info(token)) Ok(visitor.get_info(token))
} else { } else {
Self::send_log("not found")?; send_log("not found")?;
Ok(None) Ok(None)
} }
} }
pub(crate) fn show_definition(&mut self, msg: &Value) -> ELSResult<()> { pub(crate) fn show_definition(&mut self, msg: &Value) -> ELSResult<()> {
Self::send_log(format!("definition requested: {msg}"))?; send_log(format!("definition requested: {msg}"))?;
let params = GotoDefinitionParams::deserialize(&msg["params"])?; let params = GotoDefinitionParams::deserialize(&msg["params"])?;
let uri = util::normalize_url(params.text_document_position_params.text_document.uri); let uri = util::normalize_url(params.text_document_position_params.text_document.uri);
let pos = params.text_document_position_params.position; let pos = params.text_document_position_params.position;
@ -38,13 +38,13 @@ impl<Checker: BuildRunnable> Server<Checker> {
match (vi.def_loc.module, util::loc_to_range(vi.def_loc.loc)) { match (vi.def_loc.module, util::loc_to_range(vi.def_loc.loc)) {
(Some(path), Some(range)) => { (Some(path), Some(range)) => {
let def_uri = util::normalize_url(Url::from_file_path(path).unwrap()); let def_uri = util::normalize_url(Url::from_file_path(path).unwrap());
Self::send_log("found")?; send_log("found")?;
GotoDefinitionResponse::Array(vec![lsp_types::Location::new( GotoDefinitionResponse::Array(vec![lsp_types::Location::new(
def_uri, range, def_uri, range,
)]) )])
} }
_ => { _ => {
Self::send_log("not found (maybe builtin)")?; send_log("not found (maybe builtin)")?;
GotoDefinitionResponse::Array(vec![]) GotoDefinitionResponse::Array(vec![])
} }
} }
@ -52,11 +52,9 @@ impl<Checker: BuildRunnable> Server<Checker> {
GotoDefinitionResponse::Array(vec![]) GotoDefinitionResponse::Array(vec![])
} }
} else { } else {
Self::send_log("lex error occurred")?; send_log("lex error occurred")?;
GotoDefinitionResponse::Array(vec![]) GotoDefinitionResponse::Array(vec![])
}; };
Self::send( send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }))
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }),
)
} }
} }

View file

@ -8,12 +8,12 @@ use erg_compiler::error::CompileErrors;
use lsp_types::{Diagnostic, DiagnosticSeverity, Position, PublishDiagnosticsParams, Range, Url}; use lsp_types::{Diagnostic, DiagnosticSeverity, Position, PublishDiagnosticsParams, Range, Url};
use crate::server::{ELSResult, Server}; use crate::server::{send, send_log, ELSResult, Server};
use crate::util; use crate::util;
impl<Checker: BuildRunnable> Server<Checker> { impl<Checker: BuildRunnable> Server<Checker> {
pub(crate) fn check_file<S: Into<String>>(&mut self, uri: Url, code: S) -> ELSResult<()> { pub(crate) fn check_file<S: Into<String>>(&mut self, uri: Url, code: S) -> ELSResult<()> {
Self::send_log(format!("checking {uri}"))?; send_log(format!("checking {uri}"))?;
let path = util::uri_to_path(&uri); let path = util::uri_to_path(&uri);
let mode = if path.to_string_lossy().ends_with(".d.er") { let mode = if path.to_string_lossy().ends_with(".d.er") {
"declare" "declare"
@ -27,19 +27,19 @@ impl<Checker: BuildRunnable> Server<Checker> {
}; };
match checker.build(code.into(), mode) { match checker.build(code.into(), mode) {
Ok(artifact) => { Ok(artifact) => {
Self::send_log(format!("checking {uri} passed"))?; send_log(format!("checking {uri} passed"))?;
let uri_and_diags = self.make_uri_and_diags(uri.clone(), artifact.warns.clone()); let uri_and_diags = self.make_uri_and_diags(uri.clone(), artifact.warns.clone());
// clear previous diagnostics // clear previous diagnostics
self.send_diagnostics(uri.clone(), vec![])?; self.send_diagnostics(uri.clone(), vec![])?;
for (uri, diags) in uri_and_diags.into_iter() { for (uri, diags) in uri_and_diags.into_iter() {
Self::send_log(format!("{uri}, warns: {}", diags.len()))?; send_log(format!("{uri}, warns: {}", diags.len()))?;
self.send_diagnostics(uri, diags)?; self.send_diagnostics(uri, diags)?;
} }
self.artifacts.insert(uri.clone(), artifact.into()); self.artifacts.insert(uri.clone(), artifact.into());
} }
Err(artifact) => { Err(artifact) => {
Self::send_log(format!("found errors: {}", artifact.errors.len()))?; send_log(format!("found errors: {}", artifact.errors.len()))?;
Self::send_log(format!("found warns: {}", artifact.warns.len()))?; send_log(format!("found warns: {}", artifact.warns.len()))?;
let diags = artifact let diags = artifact
.errors .errors
.clone() .clone()
@ -51,14 +51,14 @@ impl<Checker: BuildRunnable> Server<Checker> {
self.send_diagnostics(uri.clone(), vec![])?; self.send_diagnostics(uri.clone(), vec![])?;
} }
for (uri, diags) in uri_and_diags.into_iter() { for (uri, diags) in uri_and_diags.into_iter() {
Self::send_log(format!("{uri}, errs & warns: {}", diags.len()))?; send_log(format!("{uri}, errs & warns: {}", diags.len()))?;
self.send_diagnostics(uri, diags)?; self.send_diagnostics(uri, diags)?;
} }
self.artifacts.insert(uri.clone(), artifact); self.artifacts.insert(uri.clone(), artifact);
} }
} }
if let Some(module) = checker.pop_context() { if let Some(module) = checker.pop_context() {
Self::send_log(format!("{uri}: {}", module.context.name))?; send_log(format!("{uri}: {}", module.context.name))?;
self.modules.insert(uri.clone(), module); self.modules.insert(uri.clone(), module);
} }
let dependents = self.dependents_of(&uri); let dependents = self.dependents_of(&uri);
@ -132,13 +132,13 @@ impl<Checker: BuildRunnable> Server<Checker> {
.map(|doc| doc.publish_diagnostics.is_some()) .map(|doc| doc.publish_diagnostics.is_some())
.unwrap_or(false) .unwrap_or(false)
{ {
Self::send(&json!({ send(&json!({
"jsonrpc": "2.0", "jsonrpc": "2.0",
"method": "textDocument/publishDiagnostics", "method": "textDocument/publishDiagnostics",
"params": params, "params": params,
}))?; }))?;
} else { } else {
Self::send_log("the client does not support diagnostics")?; send_log("the client does not support diagnostics")?;
} }
Ok(()) Ok(())
} }

View file

@ -9,7 +9,7 @@ use erg_compiler::varinfo::AbsLocation;
use lsp_types::{HoverContents, HoverParams, MarkedString, Url}; use lsp_types::{HoverContents, HoverParams, MarkedString, Url};
use crate::server::{ELSResult, Server}; use crate::server::{send, send_log, ELSResult, Server};
use crate::util; use crate::util;
const PROG_LANG: &str = if cfg!(feature = "py_compatible") { const PROG_LANG: &str = if cfg!(feature = "py_compatible") {
@ -99,7 +99,7 @@ macro_rules! next {
impl<Checker: BuildRunnable> Server<Checker> { impl<Checker: BuildRunnable> Server<Checker> {
pub(crate) fn show_hover(&mut self, msg: &Value) -> ELSResult<()> { pub(crate) fn show_hover(&mut self, msg: &Value) -> ELSResult<()> {
Self::send_log(format!("hover requested : {msg}"))?; send_log(format!("hover requested : {msg}"))?;
let params = HoverParams::deserialize(&msg["params"])?; let params = HoverParams::deserialize(&msg["params"])?;
let uri = util::normalize_url(params.text_document_position_params.text_document.uri); let uri = util::normalize_url(params.text_document_position_params.text_document.uri);
let pos = params.text_document_position_params.position; let pos = params.text_document_position_params.position;
@ -184,12 +184,10 @@ impl<Checker: BuildRunnable> Server<Checker> {
} }
} }
} else { } else {
Self::send_log("lex error")?; send_log("lex error")?;
} }
let result = json!({ "contents": HoverContents::Array(sort_hovers(contents)) }); let result = json!({ "contents": HoverContents::Array(sort_hovers(contents)) });
Self::send( send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }))
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }),
)
} }
pub(crate) fn show_doc_comment( pub(crate) fn show_doc_comment(

View file

@ -15,7 +15,7 @@ use erg_compiler::artifact::{BuildRunnable, IncompleteArtifact};
use erg_compiler::hir::{Block, Call, ClassDef, Def, Expr, Lambda, Params, PatchDef, Signature}; use erg_compiler::hir::{Block, Call, ClassDef, Def, Expr, Lambda, Params, PatchDef, Signature};
use lsp_types::{InlayHint, InlayHintKind, InlayHintLabel, InlayHintParams}; use lsp_types::{InlayHint, InlayHintKind, InlayHintLabel, InlayHintParams};
use crate::server::{ELSResult, Server}; use crate::server::{send, send_log, ELSResult, Server};
use crate::util; use crate::util;
use crate::util::loc_to_range; use crate::util::loc_to_range;
@ -90,7 +90,7 @@ fn param_anot<D: std::fmt::Display>(ln_begin: u32, col_begin: u32, name: D) -> I
impl<Checker: BuildRunnable> Server<Checker> { impl<Checker: BuildRunnable> Server<Checker> {
pub(crate) fn get_inlay_hint(&mut self, msg: &Value) -> ELSResult<()> { pub(crate) fn get_inlay_hint(&mut self, msg: &Value) -> ELSResult<()> {
Self::send_log(format!("inlay hint request: {msg}"))?; send_log(format!("inlay hint request: {msg}"))?;
let params = InlayHintParams::deserialize(&msg["params"])?; let params = InlayHintParams::deserialize(&msg["params"])?;
let uri = util::normalize_url(params.text_document.uri); let uri = util::normalize_url(params.text_document.uri);
let mut result = vec![]; let mut result = vec![];
@ -102,9 +102,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
result.extend(self.get_expr_hint(chunk)); result.extend(self.get_expr_hint(chunk));
} }
} }
Self::send( send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }))
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }),
)
} }
fn get_expr_hint(&self, expr: &Expr) -> Vec<InlayHint> { fn get_expr_hint(&self, expr: &Expr) -> Vec<InlayHint> {

View file

@ -7,7 +7,7 @@ use erg_compiler::varinfo::AbsLocation;
use lsp_types::{Position, ReferenceParams, Url}; use lsp_types::{Position, ReferenceParams, Url};
use crate::server::{ELSResult, Server}; use crate::server::{send, ELSResult, Server};
use crate::util; use crate::util;
impl<Checker: BuildRunnable> Server<Checker> { impl<Checker: BuildRunnable> Server<Checker> {
@ -16,14 +16,12 @@ impl<Checker: BuildRunnable> Server<Checker> {
let uri = util::normalize_url(params.text_document_position.text_document.uri); let uri = util::normalize_url(params.text_document_position.text_document.uri);
let pos = params.text_document_position.position; let pos = params.text_document_position.position;
let result = self.show_refs_inner(&uri, pos); let result = self.show_refs_inner(&uri, pos);
Self::send( send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }))
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }),
)
} }
fn show_refs_inner(&self, uri: &Url, pos: Position) -> Vec<lsp_types::Location> { fn show_refs_inner(&self, uri: &Url, pos: Position) -> Vec<lsp_types::Location> {
if let Some(tok) = self.file_cache.get_token(uri, pos) { if let Some(tok) = self.file_cache.get_token(uri, pos) {
// Self::send_log(format!("token: {tok}"))?; // send_log(format!("token: {tok}"))?;
if let Some(visitor) = self.get_visitor(uri) { if let Some(visitor) = self.get_visitor(uri) {
if let Some(vi) = visitor.get_info(&tok) { if let Some(vi) = visitor.get_info(&tok) {
return self.get_refs_from_abs_loc(&vi.def_loc); return self.get_refs_from_abs_loc(&vi.def_loc);
@ -36,7 +34,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
pub(crate) fn get_refs_from_abs_loc(&self, referee: &AbsLocation) -> Vec<lsp_types::Location> { pub(crate) fn get_refs_from_abs_loc(&self, referee: &AbsLocation) -> Vec<lsp_types::Location> {
let mut refs = vec![]; let mut refs = vec![];
if let Some(value) = self.get_index().get_refs(referee) { if let Some(value) = self.get_index().get_refs(referee) {
// Self::send_log(format!("referrers: {referrers:?}"))?; // send_log(format!("referrers: {referrers:?}"))?;
for referrer in value.referrers.iter() { for referrer in value.referrers.iter() {
if let (Some(path), Some(range)) = if let (Some(path), Some(range)) =
(&referrer.module, util::loc_to_range(referrer.loc)) (&referrer.module, util::loc_to_range(referrer.loc))

View file

@ -20,17 +20,17 @@ use lsp_types::{
RenameFilesParams, RenameParams, ResourceOp, TextDocumentEdit, TextEdit, Url, WorkspaceEdit, RenameFilesParams, RenameParams, ResourceOp, TextDocumentEdit, TextEdit, Url, WorkspaceEdit,
}; };
use crate::server::{ELSResult, Server}; use crate::server::{send, send_error_info, send_log, ELSResult, Server};
use crate::util; use crate::util;
impl<Checker: BuildRunnable> Server<Checker> { impl<Checker: BuildRunnable> Server<Checker> {
pub(crate) fn rename(&mut self, msg: &Value) -> ELSResult<()> { pub(crate) fn rename(&mut self, msg: &Value) -> ELSResult<()> {
let params = RenameParams::deserialize(&msg["params"])?; let params = RenameParams::deserialize(&msg["params"])?;
Self::send_log(format!("rename request: {params:?}"))?; send_log(format!("rename request: {params:?}"))?;
let uri = util::normalize_url(params.text_document_position.text_document.uri); let uri = util::normalize_url(params.text_document_position.text_document.uri);
let pos = params.text_document_position.position; let pos = params.text_document_position.position;
if let Some(tok) = self.file_cache.get_token(&uri, pos) { if let Some(tok) = self.file_cache.get_token(&uri, pos) {
// Self::send_log(format!("token: {tok}"))?; // send_log(format!("token: {tok}"))?;
if let Some(visitor) = self.get_visitor(&uri) { if let Some(visitor) = self.get_visitor(&uri) {
if let Some(vi) = visitor.get_info(&tok) { if let Some(vi) = visitor.get_info(&tok) {
let mut changes: HashMap<Url, Vec<TextEdit>> = HashMap::new(); let mut changes: HashMap<Url, Vec<TextEdit>> = HashMap::new();
@ -61,14 +61,14 @@ impl<Checker: BuildRunnable> Server<Checker> {
_ => format!("this {kind} cannot be renamed"), _ => format!("this {kind} cannot be renamed"),
}; };
let edit = WorkspaceEdit::new(changes); let edit = WorkspaceEdit::new(changes);
Self::send( send(
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": edit }), &json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": edit }),
)?; )?;
return Self::send_error_info(error_reason); return send_error_info(error_reason);
} }
Self::commit_change(&mut changes, &vi.def_loc, params.new_name.clone()); Self::commit_change(&mut changes, &vi.def_loc, params.new_name.clone());
if let Some(value) = self.get_index().get_refs(&vi.def_loc) { if let Some(value) = self.get_index().get_refs(&vi.def_loc) {
// Self::send_log(format!("referrers: {referrers:?}"))?; // send_log(format!("referrers: {referrers:?}"))?;
for referrer in value.referrers.iter() { for referrer in value.referrers.iter() {
Self::commit_change(&mut changes, referrer, params.new_name.clone()); Self::commit_change(&mut changes, referrer, params.new_name.clone());
} }
@ -79,11 +79,11 @@ impl<Checker: BuildRunnable> Server<Checker> {
} }
let timestamps = self.get_timestamps(changes.keys()); let timestamps = self.get_timestamps(changes.keys());
let edit = WorkspaceEdit::new(changes); let edit = WorkspaceEdit::new(changes);
Self::send( send(
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": edit }), &json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": edit }),
)?; )?;
for _ in 0..20 { for _ in 0..20 {
Self::send_log("waiting for file to be modified...")?; send_log("waiting for file to be modified...")?;
if self.all_changed(&timestamps) { if self.all_changed(&timestamps) {
break; break;
} }
@ -99,9 +99,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
} }
} }
} }
Self::send( send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": Value::Null }))
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": Value::Null }),
)
} }
fn commit_change( fn commit_change(
@ -269,7 +267,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
} }
pub(crate) fn rename_files(&mut self, msg: &Value) -> ELSResult<()> { pub(crate) fn rename_files(&mut self, msg: &Value) -> ELSResult<()> {
Self::send_log("workspace/willRenameFiles request")?; send_log("workspace/willRenameFiles request")?;
let params = RenameFilesParams::deserialize(msg["params"].clone())?; let params = RenameFilesParams::deserialize(msg["params"].clone())?;
let mut edits = HashMap::new(); let mut edits = HashMap::new();
let mut renames = vec![]; let mut renames = vec![];
@ -307,6 +305,6 @@ impl<Checker: BuildRunnable> Server<Checker> {
document_changes: Some(changes), document_changes: Some(changes),
..Default::default() ..Default::default()
}; };
Self::send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": edit })) send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": edit }))
} }
} }

View file

@ -17,7 +17,7 @@ use erg_compiler::ASTBuilder;
use lsp_types::{SemanticTokenType, SemanticTokens, SemanticTokensParams}; use lsp_types::{SemanticTokenType, SemanticTokens, SemanticTokensParams};
use crate::server::{ELSResult, Server}; use crate::server::{send, send_log, ELSResult, Server};
use crate::util; use crate::util;
#[derive(Debug)] #[derive(Debug)]
@ -284,7 +284,7 @@ impl ASTSemanticState {
impl<Checker: BuildRunnable> Server<Checker> { impl<Checker: BuildRunnable> Server<Checker> {
pub(crate) fn get_semantic_tokens_full(&mut self, msg: &Value) -> ELSResult<()> { pub(crate) fn get_semantic_tokens_full(&mut self, msg: &Value) -> ELSResult<()> {
Self::send_log(format!("full semantic tokens request: {msg}"))?; send_log(format!("full semantic tokens request: {msg}"))?;
let params = SemanticTokensParams::deserialize(&msg["params"])?; let params = SemanticTokensParams::deserialize(&msg["params"])?;
let uri = util::normalize_url(params.text_document.uri); let uri = util::normalize_url(params.text_document.uri);
let path = util::uri_to_path(&uri); let path = util::uri_to_path(&uri);
@ -298,8 +298,6 @@ impl<Checker: BuildRunnable> Server<Checker> {
} }
Err(_) => json!(null), Err(_) => json!(null),
}; };
Self::send( send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }))
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }),
)
} }
} }

View file

@ -16,6 +16,7 @@ use erg_common::normalize_path;
use erg_compiler::artifact::{BuildRunnable, IncompleteArtifact}; use erg_compiler::artifact::{BuildRunnable, IncompleteArtifact};
use erg_compiler::build_hir::HIRBuilder; use erg_compiler::build_hir::HIRBuilder;
use erg_compiler::context::{Context, ModuleContext}; use erg_compiler::context::{Context, ModuleContext};
use erg_compiler::hir::Expr;
use erg_compiler::module::{SharedCompilerResource, SharedModuleIndex}; use erg_compiler::module::{SharedCompilerResource, SharedModuleIndex};
use erg_compiler::ty::HasType; use erg_compiler::ty::HasType;
@ -71,7 +72,7 @@ impl From<&str> for ELSFeatures {
macro_rules! _log { macro_rules! _log {
($($arg:tt)*) => { ($($arg:tt)*) => {
Self::send_log(format!($($arg)*)).unwrap(); send_log(format!($($arg)*)).unwrap();
}; };
} }
@ -110,6 +111,34 @@ fn read_exact(len: usize) -> io::Result<Vec<u8>> {
}) })
} }
pub(crate) fn send<T: ?Sized + Serialize>(message: &T) -> ELSResult<()> {
send_stdout(message)
}
pub(crate) fn send_log<S: Into<String>>(msg: S) -> ELSResult<()> {
send(&LogMessage::new(msg))
}
#[allow(unused)]
pub(crate) fn send_info<S: Into<String>>(msg: S) -> ELSResult<()> {
send(&ShowMessage::info(msg))
}
pub(crate) fn send_error_info<S: Into<String>>(msg: S) -> ELSResult<()> {
send(&ShowMessage::error(msg))
}
pub(crate) fn send_error<S: Into<String>>(id: Option<i64>, code: i64, msg: S) -> ELSResult<()> {
send(&ErrorMessage::new(
id,
json!({ "code": code, "message": msg.into() }),
))
}
pub(crate) fn send_invalid_req_error() -> ELSResult<()> {
send_error(None, -32601, "received an invalid request")
}
/// A Language Server, which can be used any object implementing `BuildRunnable` internally by passing it as a generic parameter. /// A Language Server, which can be used any object implementing `BuildRunnable` internally by passing it as a generic parameter.
#[derive(Debug)] #[derive(Debug)]
pub struct Server<Checker: BuildRunnable = HIRBuilder> { pub struct Server<Checker: BuildRunnable = HIRBuilder> {
@ -120,7 +149,8 @@ pub struct Server<Checker: BuildRunnable = HIRBuilder> {
pub(crate) file_cache: FileCache, pub(crate) file_cache: FileCache,
pub(crate) modules: Dict<Url, ModuleContext>, pub(crate) modules: Dict<Url, ModuleContext>,
pub(crate) artifacts: Dict<Url, IncompleteArtifact>, pub(crate) artifacts: Dict<Url, IncompleteArtifact>,
_checker: std::marker::PhantomData<Checker>, pub(crate) current_sig: Option<Expr>,
pub(crate) _checker: std::marker::PhantomData<Checker>,
} }
impl<Checker: BuildRunnable> Server<Checker> { impl<Checker: BuildRunnable> Server<Checker> {
@ -133,6 +163,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
file_cache: FileCache::new(), file_cache: FileCache::new(),
modules: Dict::new(), modules: Dict::new(),
artifacts: Dict::new(), artifacts: Dict::new(),
current_sig: None,
_checker: std::marker::PhantomData, _checker: std::marker::PhantomData,
} }
} }
@ -155,11 +186,11 @@ impl<Checker: BuildRunnable> Server<Checker> {
#[allow(clippy::field_reassign_with_default)] #[allow(clippy::field_reassign_with_default)]
fn init(&mut self, msg: &Value, id: i64) -> ELSResult<()> { fn init(&mut self, msg: &Value, id: i64) -> ELSResult<()> {
Self::send_log("initializing ELS")?; send_log("initializing ELS")?;
// #[allow(clippy::collapsible_if)] // #[allow(clippy::collapsible_if)]
if msg.get("params").is_some() && msg["params"].get("capabilities").is_some() { if msg.get("params").is_some() && msg["params"].get("capabilities").is_some() {
self.client_capas = ClientCapabilities::deserialize(&msg["params"]["capabilities"])?; self.client_capas = ClientCapabilities::deserialize(&msg["params"]["capabilities"])?;
// Self::send_log(format!("set client capabilities: {:?}", self.client_capas))?; // send_log(format!("set client capabilities: {:?}", self.client_capas))?;
} }
let mut args = self.cfg.runtime_args.iter(); let mut args = self.cfg.runtime_args.iter();
let mut disabled_features = vec![]; let mut disabled_features = vec![];
@ -247,7 +278,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
result.capabilities.code_lens_provider = Some(CodeLensOptions { result.capabilities.code_lens_provider = Some(CodeLensOptions {
resolve_provider: Some(false), resolve_provider: Some(false),
}); });
Self::send(&json!({ send(&json!({
"jsonrpc": "2.0", "jsonrpc": "2.0",
"id": id, "id": id,
"result": result, "result": result,
@ -255,13 +286,13 @@ impl<Checker: BuildRunnable> Server<Checker> {
} }
fn exit(&self) -> ELSResult<()> { fn exit(&self) -> ELSResult<()> {
Self::send_log("exiting ELS")?; send_log("exiting ELS")?;
std::process::exit(0); std::process::exit(0);
} }
fn shutdown(&self, id: i64) -> ELSResult<()> { fn shutdown(&self, id: i64) -> ELSResult<()> {
Self::send_log("shutting down ELS")?; send_log("shutting down ELS")?;
Self::send(&json!({ send(&json!({
"jsonrpc": "2.0", "jsonrpc": "2.0",
"id": id, "id": id,
"result": json!(null), "result": json!(null),
@ -346,7 +377,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
Ok(()) Ok(())
} }
(None, Some(notification)) => self.handle_notification(&msg, notification), (None, Some(notification)) => self.handle_notification(&msg, notification),
_ => Self::send_invalid_req_error(), _ => send_invalid_req_error(),
} }
} }
@ -367,19 +398,19 @@ impl<Checker: BuildRunnable> Server<Checker> {
"textDocument/codeLens" => self.show_code_lens(msg), "textDocument/codeLens" => self.show_code_lens(msg),
"workspace/willRenameFiles" => self.rename_files(msg), "workspace/willRenameFiles" => self.rename_files(msg),
"workspace/executeCommand" => self.execute_command(msg), "workspace/executeCommand" => self.execute_command(msg),
other => Self::send_error(Some(id), -32600, format!("{other} is not supported")), other => send_error(Some(id), -32600, format!("{other} is not supported")),
} }
} }
fn handle_notification(&mut self, msg: &Value, method: &str) -> ELSResult<()> { fn handle_notification(&mut self, msg: &Value, method: &str) -> ELSResult<()> {
match method { match method {
"initialized" => Self::send_log("successfully bound"), "initialized" => send_log("successfully bound"),
"exit" => self.exit(), "exit" => self.exit(),
"textDocument/didOpen" => { "textDocument/didOpen" => {
let uri = util::parse_and_normalize_url( let uri = util::parse_and_normalize_url(
msg["params"]["textDocument"]["uri"].as_str().unwrap(), msg["params"]["textDocument"]["uri"].as_str().unwrap(),
)?; )?;
Self::send_log(format!("{method}: {uri}"))?; send_log(format!("{method}: {uri}"))?;
let code = msg["params"]["textDocument"]["text"].as_str().unwrap(); let code = msg["params"]["textDocument"]["text"].as_str().unwrap();
self.file_cache.update(&uri, code.to_string()); self.file_cache.update(&uri, code.to_string());
self.check_file(uri, code) self.check_file(uri, code)
@ -388,49 +419,21 @@ impl<Checker: BuildRunnable> Server<Checker> {
let uri = util::parse_and_normalize_url( let uri = util::parse_and_normalize_url(
msg["params"]["textDocument"]["uri"].as_str().unwrap(), msg["params"]["textDocument"]["uri"].as_str().unwrap(),
)?; )?;
Self::send_log(format!("{method}: {uri}"))?; send_log(format!("{method}: {uri}"))?;
let code = util::get_code_from_uri(&uri)?; let code = util::get_code_from_uri(&uri)?;
self.clear_cache(&uri); self.clear_cache(&uri);
self.check_file(uri, &code) self.check_file(uri, &code)
} }
"textDocument/didChange" => { "textDocument/didChange" => {
let params = DidChangeTextDocumentParams::deserialize(msg["params"].clone())?; let params = DidChangeTextDocumentParams::deserialize(msg["params"].clone())?;
// Self::send_log(format!("{method}: {params:?}"))?;
self.file_cache.incremental_update(params); self.file_cache.incremental_update(params);
send_log("file cache updated")?;
Ok(()) Ok(())
} }
_ => Self::send_log(format!("received notification: {method}")), _ => send_log(format!("received notification: {method}")),
} }
} }
pub(crate) fn send<T: ?Sized + Serialize>(message: &T) -> ELSResult<()> {
send_stdout(message)
}
pub(crate) fn send_log<S: Into<String>>(msg: S) -> ELSResult<()> {
Self::send(&LogMessage::new(msg))
}
#[allow(unused)]
pub(crate) fn send_info<S: Into<String>>(msg: S) -> ELSResult<()> {
Self::send(&ShowMessage::info(msg))
}
pub(crate) fn send_error_info<S: Into<String>>(msg: S) -> ELSResult<()> {
Self::send(&ShowMessage::error(msg))
}
pub(crate) fn send_error<S: Into<String>>(id: Option<i64>, code: i64, msg: S) -> ELSResult<()> {
Self::send(&ErrorMessage::new(
id,
json!({ "code": code, "message": msg.into() }),
))
}
pub(crate) fn send_invalid_req_error() -> ELSResult<()> {
Self::send_error(None, -32601, "received an invalid request")
}
pub(crate) fn get_visitor(&self, uri: &Url) -> Option<HIRVisitor> { pub(crate) fn get_visitor(&self, uri: &Url) -> Option<HIRVisitor> {
self.artifacts self.artifacts
.get(uri)? .get(uri)?
@ -440,7 +443,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
} }
pub(crate) fn get_local_ctx(&self, uri: &Url, pos: Position) -> Vec<&Context> { pub(crate) fn get_local_ctx(&self, uri: &Url, pos: Position) -> Vec<&Context> {
// Self::send_log(format!("scope: {:?}\n", self.module.as_ref().unwrap().scope.keys())).unwrap(); // send_log(format!("scope: {:?}\n", self.module.as_ref().unwrap().scope.keys())).unwrap();
let mut ctxs = vec![]; let mut ctxs = vec![];
if let Some(visitor) = self.get_visitor(uri) { if let Some(visitor) = self.get_visitor(uri) {
let ns = visitor.get_namespace(pos); let ns = visitor.get_namespace(pos);
@ -467,7 +470,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
.file_cache .file_cache
.get_token_relatively(uri, attr_marker_pos, -2)?; .get_token_relatively(uri, attr_marker_pos, -2)?;
if let Some(token) = maybe_token { if let Some(token) = maybe_token {
Self::send_log(format!("token: {token}"))?; // send_log(format!("token: {token}"))?;
let mut ctxs = vec![]; let mut ctxs = vec![];
if let Some(visitor) = self.get_visitor(uri) { if let Some(visitor) = self.get_visitor(uri) {
if let Some(expr) = visitor.get_min_expr(&token) { if let Some(expr) = visitor.get_min_expr(&token) {
@ -482,11 +485,13 @@ impl<Checker: BuildRunnable> Server<Checker> {
{ {
ctxs.push(singular_ctx); ctxs.push(singular_ctx);
} }
} else {
send_log("expr not found: {token}")?;
} }
} }
Ok(ctxs) Ok(ctxs)
} else { } else {
Self::send_log("token not found")?; send_log("token not found")?;
Ok(vec![]) Ok(vec![])
} }
} }

View file

@ -1,19 +1,19 @@
use erg_common::traits::NoTypeDisplay;
use erg_compiler::ty::HasType;
use lsp_types::Position;
use serde::Deserialize; use serde::Deserialize;
use serde_json::json; use serde_json::json;
use serde_json::Value; use serde_json::Value;
use erg_common::traits::{DequeStream, Locational, NoTypeDisplay};
use erg_compiler::artifact::BuildRunnable; use erg_compiler::artifact::BuildRunnable;
use erg_compiler::erg_parser::token::{Token, TokenKind};
use erg_compiler::hir::Expr; use erg_compiler::hir::Expr;
use erg_compiler::ty::{HasType, ParamTy};
use lsp_types::{ use lsp_types::{
ParameterInformation, ParameterLabel, SignatureHelp, SignatureHelpParams, SignatureInformation, ParameterInformation, ParameterLabel, Position, SignatureHelp, SignatureHelpContext,
Url, SignatureHelpParams, SignatureHelpTriggerKind, SignatureInformation, Url,
}; };
use crate::server::{ELSResult, Server}; use crate::server::{send, send_log, ELSResult, Server};
use crate::util; use crate::util;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -26,7 +26,7 @@ pub enum Trigger {
impl From<String> for Trigger { impl From<String> for Trigger {
fn from(s: String) -> Self { fn from(s: String) -> Self {
match s.as_str() { match s.as_str() {
"(" | ")" => Trigger::Paren, "(" => Trigger::Paren,
"," => Trigger::Comma, "," => Trigger::Comma,
"|" => Trigger::VBar, "|" => Trigger::VBar,
_ => unreachable!(), _ => unreachable!(),
@ -34,12 +34,24 @@ impl From<String> for Trigger {
} }
} }
fn get_end(start: usize, pt: &ParamTy) -> usize {
start + pt.name().unwrap().len() + 2 + pt.typ().to_string().len()
}
impl<Checker: BuildRunnable> Server<Checker> { impl<Checker: BuildRunnable> Server<Checker> {
pub(crate) fn show_signature_help(&mut self, msg: &Value) -> ELSResult<()> { pub(crate) fn show_signature_help(&mut self, msg: &Value) -> ELSResult<()> {
Self::send_log(format!("signature help requested: {msg}"))?; send_log(format!("signature help requested: {msg}"))?;
let params = SignatureHelpParams::deserialize(&msg["params"])?; let params = SignatureHelpParams::deserialize(&msg["params"])?;
let uri = util::normalize_url(params.text_document_position_params.text_document.uri); let uri = util::normalize_url(params.text_document_position_params.text_document.uri);
let pos = params.text_document_position_params.position; let pos = params.text_document_position_params.position;
if params.context.as_ref().map(|ctx| &ctx.trigger_kind)
== Some(&SignatureHelpTriggerKind::CONTENT_CHANGE)
{
let help = self.resend_help(&uri, pos, params.context.as_ref().unwrap());
return send(
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": help }),
);
}
let trigger = params let trigger = params
.context .context
.and_then(|c| c.trigger_character) .and_then(|c| c.trigger_character)
@ -49,79 +61,131 @@ impl<Checker: BuildRunnable> Server<Checker> {
Some(Trigger::Comma) => self.get_continuous_help(&uri, pos), Some(Trigger::Comma) => self.get_continuous_help(&uri, pos),
Some(Trigger::VBar) | None => None, Some(Trigger::VBar) | None => None,
}; };
Self::send( send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }))
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }),
)
} }
fn get_first_help(&self, uri: &Url, pos: Position) -> Option<SignatureHelp> { fn nth(&self, uri: &Url, args_loc: erg_common::error::Location, token: &Token) -> usize {
if let Some(token) = self.file_cache.get_token_relatively(uri, pos, -1).ok()? { // we should use the latest commas
let commas = self
.file_cache
.get_token_stream(uri)
.unwrap()
.iter()
.skip_while(|&tk| tk.loc() < args_loc)
.filter(|tk| tk.is(TokenKind::Comma) && args_loc.ln_end() >= tk.ln_begin())
.collect::<Vec<_>>();
let argc = commas.len();
commas
.iter()
.position(|c| c.col_end().unwrap() >= token.col_end().unwrap())
.unwrap_or(argc) // `commas.col_end() < token.col_end()` means the token is the last argument
}
fn resend_help(
&mut self,
uri: &Url,
pos: Position,
ctx: &SignatureHelpContext,
) -> Option<SignatureHelp> {
if let Some(token) = self.file_cache.get_token(uri, pos) {
send_log(format!("token: {token}")).unwrap();
if let Some(Expr::Call(call)) = &self.current_sig {
if call.ln_begin() > token.ln_begin() || call.ln_end() < token.ln_end() {
self.current_sig = None;
return None;
}
let nth = self.nth(uri, call.args.loc(), &token) as u32;
return self.make_sig_help(call.obj.as_ref(), nth);
}
} else {
send_log("lex error occurred").unwrap();
}
ctx.active_signature_help.clone()
}
fn get_first_help(&mut self, uri: &Url, pos: Position) -> Option<SignatureHelp> {
if let Some(token) = self.file_cache.get_token_relatively(uri, pos, -2).ok()? {
// send_log(format!("token before `(`: {token}")).unwrap();
if let Some(visitor) = self.get_visitor(uri) { if let Some(visitor) = self.get_visitor(uri) {
match visitor.get_min_expr(&token) { match visitor.get_min_expr(&token) {
Some(Expr::Call(call)) => { Some(Expr::Call(_call)) => {
let sig_t = call.signature_t().unwrap(); // let sig_t = call.signature_t().unwrap();
Self::send_log(format!("t: {sig_t}")).unwrap(); // send_log(format!("call: {call}")).unwrap();
} }
Some(Expr::Accessor(acc)) => { Some(Expr::Accessor(acc)) => {
let sig_t = acc.ref_t(); return self.make_sig_help(acc, 0);
let mut parameters = vec![];
for nd_param in sig_t.non_default_params()? {
let param_info = ParameterInformation {
label: ParameterLabel::Simple(
nd_param.name().map_or("".to_string(), |s| s.to_string()),
),
documentation: None, //Some(Documentation::String(nd_param.typ().to_string())),
};
parameters.push(param_info);
}
if let Some(var_params) = sig_t.var_params() {
let param_info = ParameterInformation {
label: ParameterLabel::Simple(
var_params.name().map_or("".to_string(), |s| s.to_string()),
),
documentation: None, //Some(Documentation::String(var_params.typ().to_string())),
};
parameters.push(param_info);
}
let info = SignatureInformation {
label: format!("{}: {sig_t}", acc.to_string_notype()),
documentation: None,
parameters: Some(parameters),
active_parameter: Some(0),
};
return Some(SignatureHelp {
signatures: vec![info],
active_parameter: None,
active_signature: None,
});
}
Some(other) => {
Self::send_log(format!("other: {other}")).unwrap();
} }
_ => {} _ => {}
} }
} }
} else { } else {
Self::send_log("lex error occurred").unwrap(); send_log("lex error occurred").unwrap();
} }
None None
} }
fn get_continuous_help(&self, uri: &Url, pos: Position) -> Option<SignatureHelp> { fn get_continuous_help(&mut self, uri: &Url, pos: Position) -> Option<SignatureHelp> {
if let Some(token) = self.file_cache.get_token(uri, pos) { if let Some(comma) = self.file_cache.get_token_relatively(uri, pos, -1).ok()? {
Self::send_log(format!("comma?: {token}")).unwrap(); send_log(format!("comma: {comma}")).unwrap();
if let Some(visitor) = self.get_visitor(uri) { if let Some(visitor) = self.get_visitor(uri) {
#[allow(clippy::single_match)] #[allow(clippy::single_match)]
match visitor.get_min_expr(&token) { match visitor.get_min_expr(&comma) {
Some(Expr::Call(call)) => { Some(Expr::Call(call)) => {
Self::send_log(format!("call: {call}")).unwrap(); let nth = self.nth(uri, call.args.loc(), &comma) as u32 + 1;
let help = self.make_sig_help(call.obj.as_ref(), nth);
self.current_sig = Some(Expr::Call(call.clone()));
return help;
} }
_ => {} _ => {}
} }
} else {
// send_log("visitor not found").unwrap();
} }
} else { } else {
Self::send_log("lex error occurred").unwrap(); send_log("lex error occurred").unwrap();
} }
None None
} }
fn make_sig_help<S: HasType + NoTypeDisplay>(
&self,
sig: &S,
nth: u32,
) -> Option<SignatureHelp> {
let sig_t = sig.ref_t();
let mut parameters = vec![];
let label = format!("{}: {sig_t}", sig.to_string_notype());
for nd_param in sig_t.non_default_params()? {
let start = label.find(&nd_param.name().unwrap()[..]).unwrap();
let end = get_end(start, nd_param);
let param_info = ParameterInformation {
label: ParameterLabel::LabelOffsets([start as u32, end as u32]),
documentation: None, //Some(Documentation::String(nd_param.typ().to_string())),
};
parameters.push(param_info);
}
if let Some(var_params) = sig_t.var_params() {
// var_params.name().is_none() => skip
if let Some(start) = label.find(var_params.name().map_or("#", |s| &s[..])) {
let end = get_end(start, var_params);
let param_info = ParameterInformation {
label: ParameterLabel::LabelOffsets([start as u32, end as u32]),
documentation: None, //Some(Documentation::String(var_params.typ().to_string())),
};
parameters.push(param_info);
}
}
let nth = (parameters.len() as u32 - 1).min(nth);
let info = SignatureInformation {
label,
documentation: None,
parameters: Some(parameters),
active_parameter: Some(nth),
};
Some(SignatureHelp {
signatures: vec![info],
active_parameter: None,
active_signature: None,
})
}
} }

View file

@ -25,6 +25,10 @@ pub fn loc_to_pos(loc: erg_common::error::Location) -> Option<Position> {
Some(start) Some(start)
} }
pub fn _pos_to_loc(pos: Position) -> erg_common::error::Location {
erg_common::error::Location::range(pos.line + 1, pos.character - 1, pos.line + 1, pos.character)
}
pub fn pos_in_loc<L: Locational>(loc: &L, pos: Position) -> bool { pub fn pos_in_loc<L: Locational>(loc: &L, pos: Position) -> bool {
let ln_begin = loc.ln_begin().unwrap_or(0); let ln_begin = loc.ln_begin().unwrap_or(0);
let ln_end = loc.ln_end().unwrap_or(0); let ln_end = loc.ln_end().unwrap_or(0);

View file

@ -2799,13 +2799,10 @@ impl PyCodeGenerator {
erg_parser::ast::NonDefaultParamSignature::new(ParamPattern::VarName(param), None); erg_parser::ast::NonDefaultParamSignature::new(ParamPattern::VarName(param), None);
let vi = VarInfo::parameter(new_first_param.typ().clone(), ident.vi.def_loc.clone()); let vi = VarInfo::parameter(new_first_param.typ().clone(), ident.vi.def_loc.clone());
let param = NonDefaultParamSignature::new(raw, vi, None); let param = NonDefaultParamSignature::new(raw, vi, None);
let params = Params::new(vec![self_param, param], None, vec![], None); let params = Params::new(vec![self_param, param], None, vec![], None, vec![]);
(param_name, params) (param_name, params)
} else { } else {
( ("_".into(), Params::single(self_param))
"_".into(),
Params::new(vec![self_param], None, vec![], None),
)
}; };
let bounds = TypeBoundSpecs::empty(); let bounds = TypeBoundSpecs::empty();
let subr_sig = SubrSignature::new(ident, bounds, params, sig.t_spec().cloned()); let subr_sig = SubrSignature::new(ident, bounds, params, sig.t_spec().cloned());
@ -2883,22 +2880,22 @@ impl PyCodeGenerator {
let raw = let raw =
erg_parser::ast::NonDefaultParamSignature::new(ParamPattern::VarName(param), None); erg_parser::ast::NonDefaultParamSignature::new(ParamPattern::VarName(param), None);
let param = NonDefaultParamSignature::new(raw, vi, None); let param = NonDefaultParamSignature::new(raw, vi, None);
let params = Params::new(vec![param], None, vec![], None); let params = Params::single(param);
let bounds = TypeBoundSpecs::empty(); let bounds = TypeBoundSpecs::empty();
let sig = SubrSignature::new(ident, bounds, params, sig.t_spec().cloned()); let sig = SubrSignature::new(ident, bounds, params, sig.t_spec().cloned());
let arg = PosArg::new(Expr::Accessor(Accessor::private_with_line( let arg = PosArg::new(Expr::Accessor(Accessor::private_with_line(
Str::from(param_name), Str::from(param_name),
line, line,
))); )));
let call = class_new.call_expr(Args::new(vec![arg], None, vec![], None)); let call = class_new.call_expr(Args::single(arg));
let block = Block::new(vec![call]); let block = Block::new(vec![call]);
let body = DefBody::new(EQUAL, block, DefId(0)); let body = DefBody::new(EQUAL, block, DefId(0));
self.emit_subr_def(Some(class_ident.inspect()), sig, body); self.emit_subr_def(Some(class_ident.inspect()), sig, body);
} else { } else {
let params = Params::new(vec![], None, vec![], None); let params = Params::empty();
let bounds = TypeBoundSpecs::empty(); let bounds = TypeBoundSpecs::empty();
let sig = SubrSignature::new(ident, bounds, params, sig.t_spec().cloned()); let sig = SubrSignature::new(ident, bounds, params, sig.t_spec().cloned());
let call = class_new.call_expr(Args::new(vec![], None, vec![], None)); let call = class_new.call_expr(Args::empty());
let block = Block::new(vec![call]); let block = Block::new(vec![call]);
let body = DefBody::new(EQUAL, block, DefId(0)); let body = DefBody::new(EQUAL, block, DefId(0));
self.emit_subr_def(Some(class_ident.inspect()), sig, body); self.emit_subr_def(Some(class_ident.inspect()), sig, body);

View file

@ -947,7 +947,7 @@ impl Context {
)?; )?;
let op = hir::Expr::Accessor(hir::Accessor::private(symbol, t)); let op = hir::Expr::Accessor(hir::Accessor::private(symbol, t));
self.get_call_t(&op, &None, args, &[], input, namespace) self.get_call_t(&op, &None, args, &[], input, namespace)
.map_err(|errs| { .map_err(|(_, errs)| {
let Some(op_ident ) = option_enum_unwrap!(op, hir::Expr::Accessor:(hir::Accessor::Ident:(_))) else { let Some(op_ident ) = option_enum_unwrap!(op, hir::Expr::Accessor:(hir::Accessor::Ident:(_))) else {
return errs; return errs;
}; };
@ -981,7 +981,7 @@ impl Context {
)?; )?;
let op = hir::Expr::Accessor(hir::Accessor::private(symbol, vi)); let op = hir::Expr::Accessor(hir::Accessor::private(symbol, vi));
self.get_call_t(&op, &None, args, &[], input, namespace) self.get_call_t(&op, &None, args, &[], input, namespace)
.map_err(|errs| { .map_err(|(_, errs)| {
let Some(op_ident) = option_enum_unwrap!(op, hir::Expr::Accessor:(hir::Accessor::Ident:(_))) else { let Some(op_ident) = option_enum_unwrap!(op, hir::Expr::Accessor:(hir::Accessor::Ident:(_))) else {
return errs; return errs;
}; };
@ -1575,41 +1575,62 @@ impl Context {
kw_args: &[hir::KwArg], kw_args: &[hir::KwArg],
input: &Input, input: &Input,
namespace: &Str, namespace: &Str,
) -> TyCheckResult<VarInfo> { ) -> Result<VarInfo, (Option<VarInfo>, TyCheckErrors)> {
if let hir::Expr::Accessor(hir::Accessor::Ident(local)) = obj { if let hir::Expr::Accessor(hir::Accessor::Ident(local)) = obj {
if local.vis().is_private() { if local.vis().is_private() {
match &local.inspect()[..] { match &local.inspect()[..] {
"match" => { "match" => {
return self.get_match_call_t(SubrKind::Func, pos_args, kw_args); return self
.get_match_call_t(SubrKind::Func, pos_args, kw_args)
.map_err(|errs| (None, errs));
} }
"match!" => { "match!" => {
return self.get_match_call_t(SubrKind::Proc, pos_args, kw_args); return self
.get_match_call_t(SubrKind::Proc, pos_args, kw_args)
.map_err(|errs| (None, errs));
} }
_ => {} _ => {}
} }
} }
} }
let found = self.search_callee_info(obj, attr_name, input, namespace)?; let found = self
.search_callee_info(obj, attr_name, input, namespace)
.map_err(|err| (None, TyCheckErrors::from(err)))?;
log!( log!(
"Found:\ncallee: {obj}{}\nfound: {found}", "Found:\ncallee: {obj}{}\nfound: {found}",
fmt_option!(pre ".", attr_name.as_ref().map(|ident| &ident.name)) fmt_option!(pre ".", attr_name.as_ref().map(|ident| &ident.name))
); );
let instance = self.instantiate(found.t, obj)?; let instance = self
.instantiate(found.t.clone(), obj)
.map_err(|errs| (Some(found.clone()), errs))?;
log!( log!(
"Instantiated:\ninstance: {instance}\npos_args: ({})\nkw_args: ({})", "Instantiated:\ninstance: {instance}\npos_args: ({})\nkw_args: ({})",
fmt_slice(pos_args), fmt_slice(pos_args),
fmt_slice(kw_args) fmt_slice(kw_args)
); );
let instance = match self.substitute_call(obj, attr_name, &instance, pos_args, kw_args)? { let instance = match self
.substitute_call(obj, attr_name, &instance, pos_args, kw_args)
.map_err(|errs| (Some(found.clone()), errs))?
{
SubstituteResult::Ok => instance, SubstituteResult::Ok => instance,
SubstituteResult::__Call__(__call__) => __call__, SubstituteResult::__Call__(__call__) => __call__,
SubstituteResult::Coerced(coerced) => coerced, SubstituteResult::Coerced(coerced) => coerced,
}; };
debug_assert!(!instance.is_quantified_subr()); debug_assert!(!instance.is_quantified_subr());
log!(info "Substituted:\ninstance: {instance}"); log!(info "Substituted:\ninstance: {instance}");
let res = self.eval_t_params(instance, self.level, obj)?; let res = self
.eval_t_params(instance, self.level, obj)
.map_err(|errs| (Some(found.clone()), errs))?;
log!(info "Params evaluated:\nres: {res}\n"); log!(info "Params evaluated:\nres: {res}\n");
self.propagate(&res, obj)?; self.propagate(&res, obj).map_err(|errs| {
(
Some(VarInfo {
t: res.clone(),
..found.clone()
}),
errs,
)
})?;
log!(info "Propagated:\nres: {res}\n"); log!(info "Propagated:\nres: {res}\n");
let res = VarInfo { t: res, ..found }; let res = VarInfo { t: res, ..found };
Ok(res) Ok(res)

View file

@ -153,7 +153,7 @@ impl ASTLowerer {
} }
fn fake_lower_args(&self, args: ast::Args) -> LowerResult<hir::Args> { fn fake_lower_args(&self, args: ast::Args) -> LowerResult<hir::Args> {
let (pos_args_, var_args_, kw_args_, paren) = args.deconstruct(); let (pos_args_, var_args_, kw_args_, paren, commas) = args.deconstruct();
let mut pos_args = vec![]; let mut pos_args = vec![];
for arg in pos_args_.into_iter() { for arg in pos_args_.into_iter() {
let arg = self.fake_lower_expr(arg.expr)?; let arg = self.fake_lower_expr(arg.expr)?;
@ -171,7 +171,7 @@ impl ASTLowerer {
let expr = self.fake_lower_expr(kw_arg.expr)?; let expr = self.fake_lower_expr(kw_arg.expr)?;
kw_args.push(hir::KwArg::new(kw_arg.keyword, expr)); kw_args.push(hir::KwArg::new(kw_arg.keyword, expr));
} }
let args = hir::Args::new(pos_args, var_args, kw_args, paren); let args = hir::Args::new(pos_args, var_args, kw_args, paren, commas);
Ok(args) Ok(args)
} }
@ -206,12 +206,12 @@ impl ASTLowerer {
} }
ast::Array::Normal(arr) => { ast::Array::Normal(arr) => {
let mut elems = Vec::new(); let mut elems = Vec::new();
let (elems_, ..) = arr.elems.deconstruct(); let (elems_, .., commas) = arr.elems.deconstruct();
for elem in elems_.into_iter() { for elem in elems_.into_iter() {
let elem = self.fake_lower_expr(elem.expr)?; let elem = self.fake_lower_expr(elem.expr)?;
elems.push(hir::PosArg::new(elem)); elems.push(hir::PosArg::new(elem));
} }
let elems = hir::Args::new(elems, None, vec![], None); let elems = hir::Args::new(elems, None, vec![], None, commas);
Ok(hir::Array::Normal(hir::NormalArray::new( Ok(hir::Array::Normal(hir::NormalArray::new(
arr.l_sqbr, arr.l_sqbr,
arr.r_sqbr, arr.r_sqbr,
@ -232,12 +232,12 @@ impl ASTLowerer {
match tup { match tup {
ast::Tuple::Normal(tup) => { ast::Tuple::Normal(tup) => {
let mut elems = Vec::new(); let mut elems = Vec::new();
let (elems_, _, _, paren) = tup.elems.deconstruct(); let (elems_, _, _, paren, commas) = tup.elems.deconstruct();
for elem in elems_.into_iter() { for elem in elems_.into_iter() {
let elem = self.fake_lower_expr(elem.expr)?; let elem = self.fake_lower_expr(elem.expr)?;
elems.push(hir::PosArg::new(elem)); elems.push(hir::PosArg::new(elem));
} }
let elems = hir::Args::new(elems, None, vec![], paren); let elems = hir::Args::pos_only(elems, paren, commas);
Ok(hir::Tuple::Normal(hir::NormalTuple::new(elems))) Ok(hir::Tuple::Normal(hir::NormalTuple::new(elems)))
} }
} }
@ -290,7 +290,7 @@ impl ASTLowerer {
let elem = self.fake_lower_expr(elem.expr)?; let elem = self.fake_lower_expr(elem.expr)?;
elems.push(hir::PosArg::new(elem)); elems.push(hir::PosArg::new(elem));
} }
let elems = hir::Args::new(elems, None, vec![], None); let elems = hir::Args::pos_only(elems, None, vec![]);
Ok(hir::Set::Normal(hir::NormalSet::new( Ok(hir::Set::Normal(hir::NormalSet::new(
set.l_brace, set.l_brace,
set.r_brace, set.r_brace,
@ -334,7 +334,7 @@ impl ASTLowerer {
} }
fn fake_lower_params(&self, params: ast::Params) -> LowerResult<hir::Params> { fn fake_lower_params(&self, params: ast::Params) -> LowerResult<hir::Params> {
let (non_defaults_, var_params_, defaults_, parens) = params.deconstruct(); let (non_defaults_, var_params_, defaults_, parens, commas) = params.deconstruct();
let mut non_defaults = vec![]; let mut non_defaults = vec![];
for non_default_ in non_defaults_.into_iter() { for non_default_ in non_defaults_.into_iter() {
let non_default = let non_default =
@ -355,7 +355,13 @@ impl ASTLowerer {
let default = hir::DefaultParamSignature::new(sig, default_val); let default = hir::DefaultParamSignature::new(sig, default_val);
defaults.push(default); defaults.push(default);
} }
Ok(hir::Params::new(non_defaults, var_args, defaults, parens)) Ok(hir::Params::new(
non_defaults,
var_args,
defaults,
parens,
commas,
))
} }
fn fake_lower_block(&self, block: ast::Block) -> LowerResult<hir::Block> { fn fake_lower_block(&self, block: ast::Block) -> LowerResult<hir::Block> {

View file

@ -169,6 +169,7 @@ pub struct Args {
pub var_args: Option<Box<PosArg>>, pub var_args: Option<Box<PosArg>>,
pub kw_args: Vec<KwArg>, pub kw_args: Vec<KwArg>,
pub paren: Option<(Token, Token)>, pub paren: Option<(Token, Token)>,
pub commas: Vec<Token>,
} }
impl NestedDisplay for Args { impl NestedDisplay for Args {
@ -244,26 +245,35 @@ impl Args {
var_args: Option<PosArg>, var_args: Option<PosArg>,
kw_args: Vec<KwArg>, kw_args: Vec<KwArg>,
paren: Option<(Token, Token)>, paren: Option<(Token, Token)>,
commas: Vec<Token>,
) -> Self { ) -> Self {
Self { Self {
pos_args, pos_args,
var_args: var_args.map(Box::new), var_args: var_args.map(Box::new),
kw_args, kw_args,
paren, paren,
commas,
} }
} }
pub fn values(exprs: Vec<Expr>, paren: Option<(Token, Token)>) -> Self { pub fn values(exprs: Vec<Expr>, paren: Option<(Token, Token)>, commas: Vec<Token>) -> Self {
Self::new( Self::pos_only(exprs.into_iter().map(PosArg::new).collect(), paren, commas)
exprs.into_iter().map(PosArg::new).collect(), }
None,
vec![], pub fn single(pos_arg: PosArg) -> Self {
paren, Self::pos_only(vec![pos_arg], None, vec![])
) }
pub fn pos_only(
pos_args: Vec<PosArg>,
paren: Option<(Token, Token)>,
commas: Vec<Token>,
) -> Self {
Self::new(pos_args, None, vec![], paren, commas)
} }
pub fn empty() -> Self { pub fn empty() -> Self {
Self::new(vec![], None, vec![], None) Self::new(vec![], None, vec![], None, vec![])
} }
#[inline] #[inline]
@ -1673,6 +1683,7 @@ pub struct Params {
pub var_params: Option<Box<NonDefaultParamSignature>>, pub var_params: Option<Box<NonDefaultParamSignature>>,
pub defaults: Vec<DefaultParamSignature>, pub defaults: Vec<DefaultParamSignature>,
pub parens: Option<(Token, Token)>, pub parens: Option<(Token, Token)>,
pub commas: Vec<Token>,
} }
impl fmt::Display for Params { impl fmt::Display for Params {
@ -1742,18 +1753,28 @@ type RefRawParams<'a> = (
impl Params { impl Params {
pub const fn new( pub const fn new(
non_defaults: Vec<NonDefaultParamSignature>, non_defaults: Vec<NonDefaultParamSignature>,
var_args: Option<Box<NonDefaultParamSignature>>, var_params: Option<Box<NonDefaultParamSignature>>,
defaults: Vec<DefaultParamSignature>, defaults: Vec<DefaultParamSignature>,
parens: Option<(Token, Token)>, parens: Option<(Token, Token)>,
commas: Vec<Token>,
) -> Self { ) -> Self {
Self { Self {
non_defaults, non_defaults,
var_params: var_args, var_params,
defaults, defaults,
parens, parens,
commas,
} }
} }
pub fn empty() -> Self {
Self::new(vec![], None, vec![], None, vec![])
}
pub fn single(sig: NonDefaultParamSignature) -> Self {
Self::new(vec![sig], None, vec![], None, vec![])
}
pub const fn ref_deconstruct(&self) -> RefRawParams { pub const fn ref_deconstruct(&self) -> RefRawParams {
( (
&self.non_defaults, &self.non_defaults,

View file

@ -326,7 +326,7 @@ impl<'a> Linker<'a> {
let code = Expr::Code(Block::new(Vec::from(hir.module))); let code = Expr::Code(Block::new(Vec::from(hir.module)));
let module_type = let module_type =
Expr::Accessor(Accessor::private_with_line(Str::ever("#ModuleType"), line)); Expr::Accessor(Accessor::private_with_line(Str::ever("#ModuleType"), line));
let args = Args::new(vec![PosArg::new(mod_name.clone())], None, vec![], None); let args = Args::single(PosArg::new(mod_name.clone()));
let block = Block::new(vec![module_type.call_expr(args)]); let block = Block::new(vec![module_type.call_expr(args)]);
let tmp = Identifier::private_with_line(Str::from(fresh_varname()), line); let tmp = Identifier::private_with_line(Str::from(fresh_varname()), line);
let mod_def = Expr::Def(Def::new( let mod_def = Expr::Def(Def::new(
@ -338,19 +338,14 @@ impl<'a> Linker<'a> {
let m_dict = module.clone().attr_expr(__dict__); let m_dict = module.clone().attr_expr(__dict__);
let locals = Expr::Accessor(Accessor::public_with_line(Str::ever("locals"), line)); let locals = Expr::Accessor(Accessor::public_with_line(Str::ever("locals"), line));
let locals_call = locals.call_expr(Args::empty()); let locals_call = locals.call_expr(Args::empty());
let args = Args::new(vec![PosArg::new(locals_call)], None, vec![], None); let args = Args::single(PosArg::new(locals_call));
let mod_update = Expr::Call(Call::new( let mod_update = Expr::Call(Call::new(
m_dict.clone(), m_dict.clone(),
Some(Identifier::public("update")), Some(Identifier::public("update")),
args, args,
)); ));
let exec = Expr::Accessor(Accessor::public_with_line(Str::ever("exec"), line)); let exec = Expr::Accessor(Accessor::public_with_line(Str::ever("exec"), line));
let args = Args::new( let args = Args::pos_only(vec![PosArg::new(code), PosArg::new(m_dict)], None, vec![]);
vec![PosArg::new(code), PosArg::new(m_dict)],
None,
vec![],
None,
);
let exec_code = exec.call_expr(args); let exec_code = exec.call_expr(args);
let compound = Block::new(vec![mod_def, mod_update, exec_code, module]); let compound = Block::new(vec![mod_def, mod_update, exec_code, module]);
*expr = Expr::Compound(compound); *expr = Expr::Compound(compound);

View file

@ -248,9 +248,9 @@ impl ASTLowerer {
log!(info "entered {}({array})", fn_name!()); log!(info "entered {}({array})", fn_name!());
let allow_cast = true; let allow_cast = true;
let mut new_array = vec![]; let mut new_array = vec![];
let (elems, _) = array.elems.into_iters(); let (elems, .., commas) = array.elems.deconstruct();
let mut union = Type::Never; let mut union = Type::Never;
for elem in elems { for elem in elems.into_iter() {
let elem = self.lower_expr(elem.expr)?; let elem = self.lower_expr(elem.expr)?;
let union_ = self.module.context.union(&union, elem.ref_t()); let union_ = self.module.context.union(&union, elem.ref_t());
if let Some((l, r)) = union_.union_types() { if let Some((l, r)) = union_.union_types() {
@ -291,7 +291,7 @@ impl ASTLowerer {
array.l_sqbr, array.l_sqbr,
array.r_sqbr, array.r_sqbr,
elem_t, elem_t,
hir::Args::values(new_array, None), hir::Args::values(new_array, None, commas),
)) ))
} }
@ -355,12 +355,14 @@ impl ASTLowerer {
fn lower_normal_tuple(&mut self, tuple: ast::NormalTuple) -> LowerResult<hir::NormalTuple> { fn lower_normal_tuple(&mut self, tuple: ast::NormalTuple) -> LowerResult<hir::NormalTuple> {
log!(info "entered {}({tuple})", fn_name!()); log!(info "entered {}({tuple})", fn_name!());
let mut new_tuple = vec![]; let mut new_tuple = vec![];
let (elems, .., paren) = tuple.elems.deconstruct(); let (elems, .., paren, commas) = tuple.elems.deconstruct();
for elem in elems { for elem in elems {
let elem = self.lower_expr(elem.expr)?; let elem = self.lower_expr(elem.expr)?;
new_tuple.push(elem); new_tuple.push(elem);
} }
Ok(hir::NormalTuple::new(hir::Args::values(new_tuple, paren))) Ok(hir::NormalTuple::new(hir::Args::values(
new_tuple, paren, commas,
)))
} }
fn lower_record(&mut self, record: ast::Record) -> LowerResult<hir::Record> { fn lower_record(&mut self, record: ast::Record) -> LowerResult<hir::Record> {
@ -399,7 +401,7 @@ impl ASTLowerer {
fn lower_normal_set(&mut self, set: ast::NormalSet) -> LowerResult<hir::NormalSet> { fn lower_normal_set(&mut self, set: ast::NormalSet) -> LowerResult<hir::NormalSet> {
log!(info "entered {}({set})", fn_name!()); log!(info "entered {}({set})", fn_name!());
let (elems, _) = set.elems.into_iters(); let (elems, .., commas) = set.elems.deconstruct();
let mut union = Type::Never; let mut union = Type::Never;
let mut new_set = vec![]; let mut new_set = vec![];
for elem in elems { for elem in elems {
@ -458,7 +460,7 @@ impl ASTLowerer {
} }
Ok(normal_set) Ok(normal_set)
*/ */
let elems = hir::Args::values(new_set, None); let elems = hir::Args::values(new_set, None, commas);
// check if elem_t is Eq // check if elem_t is Eq
if let Err(errs) = self if let Err(errs) = self
.module .module
@ -720,12 +722,13 @@ impl ASTLowerer {
} }
fn lower_args(&mut self, args: ast::Args, errs: &mut LowerErrors) -> hir::Args { fn lower_args(&mut self, args: ast::Args, errs: &mut LowerErrors) -> hir::Args {
let (pos_args, var_args, kw_args, paren) = args.deconstruct(); let (pos_args, var_args, kw_args, paren, commas) = args.deconstruct();
let mut hir_args = hir::Args::new( let mut hir_args = hir::Args::new(
Vec::with_capacity(pos_args.len()), Vec::with_capacity(pos_args.len()),
None, None,
Vec::with_capacity(kw_args.len()), Vec::with_capacity(kw_args.len()),
paren, paren,
commas,
); );
for arg in pos_args.into_iter() { for arg in pos_args.into_iter() {
match self.lower_expr(arg.expr) { match self.lower_expr(arg.expr) {
@ -761,6 +764,8 @@ impl ASTLowerer {
hir_args hir_args
} }
/// returning `Ok(call)` does not mean the call is valid, just means it is syntactically valid
/// `ASTLowerer` is designed to cause as little information loss in HIR as possible
pub(crate) fn lower_call(&mut self, call: ast::Call) -> LowerResult<hir::Call> { pub(crate) fn lower_call(&mut self, call: ast::Call) -> LowerResult<hir::Call> {
log!(info "entered {}({}{}(...))", fn_name!(), call.obj, fmt_option!(call.attr_name)); log!(info "entered {}({}{}(...))", fn_name!(), call.obj, fmt_option!(call.attr_name));
if let Some(name) = call.obj.get_name() { if let Some(name) = call.obj.get_name() {
@ -810,10 +815,10 @@ impl ASTLowerer {
&self.module.context.name, &self.module.context.name,
) { ) {
Ok(vi) => vi, Ok(vi) => vi,
Err(es) => { Err((vi, es)) => {
self.module.context.higher_order_caller.pop(); self.module.context.higher_order_caller.pop();
errs.extend(es); errs.extend(es);
return Err(errs); vi.unwrap_or(VarInfo::ILLEGAL.clone())
} }
}; };
let attr_name = if let Some(attr_name) = call.attr_name { let attr_name = if let Some(attr_name) = call.attr_name {
@ -877,11 +882,8 @@ impl ASTLowerer {
} }
} }
} }
if errs.is_empty() { self.errs.extend(errs);
Ok(call) Ok(call)
} else {
Err(errs)
}
} }
fn lower_pack(&mut self, pack: ast::DataPack) -> LowerResult<hir::Call> { fn lower_pack(&mut self, pack: ast::DataPack) -> LowerResult<hir::Call> {
@ -903,15 +905,21 @@ impl ASTLowerer {
pack.connector.col_begin, pack.connector.col_begin,
)), )),
); );
let vi = self.module.context.get_call_t( let vi = match self.module.context.get_call_t(
&class, &class,
&Some(attr_name.clone()), &Some(attr_name.clone()),
&args, &args,
&[], &[],
&self.cfg.input, &self.cfg.input,
&self.module.context.name, &self.module.context.name,
)?; ) {
let args = hir::Args::new(args, None, vec![], None); Ok(vi) => vi,
Err((vi, errs)) => {
self.errs.extend(errs);
vi.unwrap_or(VarInfo::ILLEGAL.clone())
}
};
let args = hir::Args::pos_only(args, None, vec![]);
let attr_name = hir::Identifier::new(attr_name.dot, attr_name.name, None, vi); let attr_name = hir::Identifier::new(attr_name.dot, attr_name.name, None, vi);
Ok(hir::Call::new(class, Some(attr_name), args)) Ok(hir::Call::new(class, Some(attr_name), args))
} }
@ -983,6 +991,7 @@ impl ASTLowerer {
hir_var_params, hir_var_params,
hir_defaults, hir_defaults,
params.parens, params.parens,
params.commas,
); );
Ok(hir_params) Ok(hir_params)
} }

View file

@ -718,6 +718,7 @@ pub enum Type {
param_ts: Vec<Type>, param_ts: Vec<Type>,
return_t: Box<Type>, return_t: Box<Type>,
}, },
// Overloaded(Vec<Type>),
Record(Dict<Field, Type>), // e.g. {x = Int} Record(Dict<Field, Type>), // e.g. {x = Int}
// e.g. {T -> T | T: Type}, {I: Int | I > 0}, {S | N: Nat; S: Str N; N > 1} // e.g. {T -> T | T: Type}, {I: Int | I > 0}, {S | N: Nat; S: Str N; N > 1}
// 区間型と列挙型は篩型に変換される // 区間型と列挙型は篩型に変換される

View file

@ -161,7 +161,9 @@ pub struct Args {
pos_args: Vec<PosArg>, pos_args: Vec<PosArg>,
pub(crate) var_args: Option<Box<PosArg>>, pub(crate) var_args: Option<Box<PosArg>>,
kw_args: Vec<KwArg>, kw_args: Vec<KwArg>,
// these are for ELS
pub paren: Option<(Token, Token)>, pub paren: Option<(Token, Token)>,
pub commas: Vec<Token>,
} }
impl NestedDisplay for Args { impl NestedDisplay for Args {
@ -199,21 +201,31 @@ impl Args {
var_args: Option<PosArg>, var_args: Option<PosArg>,
kw_args: Vec<KwArg>, kw_args: Vec<KwArg>,
paren: Option<(Token, Token)>, paren: Option<(Token, Token)>,
commas: Vec<Token>,
) -> Self { ) -> Self {
Self { Self {
pos_args, pos_args,
var_args: var_args.map(Box::new), var_args: var_args.map(Box::new),
kw_args, kw_args,
paren, paren,
commas,
} }
} }
pub fn pos_only(pos_args: Vec<PosArg>, paren: Option<(Token, Token)>) -> Self { pub fn pos_only(
Self::new(pos_args, None, vec![], paren) pos_arg: Vec<PosArg>,
paren: Option<(Token, Token)>,
commas: Vec<Token>,
) -> Self {
Self::new(pos_arg, None, vec![], paren, commas)
}
pub fn single(pos_args: PosArg) -> Self {
Self::pos_only(vec![pos_args], None, vec![])
} }
pub fn empty() -> Self { pub fn empty() -> Self {
Self::new(vec![], None, vec![], None) Self::new(vec![], None, vec![], None, vec![])
} }
// for replacing to hir::Args // for replacing to hir::Args
@ -225,12 +237,14 @@ impl Args {
Option<PosArg>, Option<PosArg>,
Vec<KwArg>, Vec<KwArg>,
Option<(Token, Token)>, Option<(Token, Token)>,
Vec<Token>,
) { ) {
( (
self.pos_args, self.pos_args,
self.var_args.map(|x| *x), self.var_args.map(|x| *x),
self.kw_args, self.kw_args,
self.paren, self.paren,
self.commas,
) )
} }
@ -294,6 +308,14 @@ impl Args {
self.kw_args.push(arg); self.kw_args.push(arg);
} }
pub fn push_comma(&mut self, comma: Token) {
self.commas.push(comma);
}
pub fn set_parens(&mut self, paren: (Token, Token)) {
self.paren = Some(paren);
}
pub fn get_left_or_key(&self, key: &str) -> Option<&Expr> { pub fn get_left_or_key(&self, key: &str) -> Option<&Expr> {
if !self.pos_args.is_empty() { if !self.pos_args.is_empty() {
self.pos_args.get(0).map(|a| &a.expr) self.pos_args.get(0).map(|a| &a.expr)
@ -1894,6 +1916,7 @@ pub struct ConstArgs {
var_args: Option<Box<ConstPosArg>>, var_args: Option<Box<ConstPosArg>>,
kw_args: Vec<ConstKwArg>, kw_args: Vec<ConstKwArg>,
paren: Option<(Token, Token)>, paren: Option<(Token, Token)>,
commas: Vec<Token>,
} }
impl NestedDisplay for ConstArgs { impl NestedDisplay for ConstArgs {
@ -1928,17 +1951,23 @@ impl ConstArgs {
var_args: Option<ConstPosArg>, var_args: Option<ConstPosArg>,
kw_args: Vec<ConstKwArg>, kw_args: Vec<ConstKwArg>,
paren: Option<(Token, Token)>, paren: Option<(Token, Token)>,
commas: Vec<Token>,
) -> Self { ) -> Self {
Self { Self {
pos_args, pos_args,
var_args: var_args.map(Box::new), var_args: var_args.map(Box::new),
kw_args, kw_args,
paren, paren,
commas,
} }
} }
pub fn pos_only(pos_args: Vec<ConstPosArg>, paren: Option<(Token, Token)>) -> Self { pub fn pos_only(
Self::new(pos_args, None, vec![], paren) pos_args: Vec<ConstPosArg>,
paren: Option<(Token, Token)>,
commas: Vec<Token>,
) -> Self {
Self::new(pos_args, None, vec![], paren, commas)
} }
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
@ -1949,17 +1978,19 @@ impl ConstArgs {
Option<ConstPosArg>, Option<ConstPosArg>,
Vec<ConstKwArg>, Vec<ConstKwArg>,
Option<(Token, Token)>, Option<(Token, Token)>,
Vec<Token>,
) { ) {
( (
self.pos_args, self.pos_args,
self.var_args.map(|x| *x), self.var_args.map(|x| *x),
self.kw_args, self.kw_args,
self.paren, self.paren,
self.commas,
) )
} }
pub fn empty() -> Self { pub fn empty() -> Self {
Self::new(vec![], None, vec![], None) Self::new(vec![], None, vec![], None, vec![])
} }
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
@ -1992,7 +2023,7 @@ impl ConstArgs {
} }
pub fn downcast(self) -> Args { pub fn downcast(self) -> Args {
let (pos_args, var_args, kw_args, paren) = self.deconstruct(); let (pos_args, var_args, kw_args, paren, commas) = self.deconstruct();
Args::new( Args::new(
pos_args pos_args
.into_iter() .into_iter()
@ -2005,6 +2036,7 @@ impl ConstArgs {
.map(|arg| KwArg::new(arg.keyword, None, arg.expr.downcast())) .map(|arg| KwArg::new(arg.keyword, None, arg.expr.downcast()))
.collect(), .collect(),
paren, paren,
commas,
) )
} }
} }
@ -2417,6 +2449,7 @@ impl TypeSpec {
None, None,
vec![], vec![],
None, None,
vec![],
)) ))
} }
} }
@ -3311,6 +3344,7 @@ pub struct Params {
pub var_params: Option<Box<NonDefaultParamSignature>>, pub var_params: Option<Box<NonDefaultParamSignature>>,
pub defaults: Vec<DefaultParamSignature>, pub defaults: Vec<DefaultParamSignature>,
pub parens: Option<(Token, Token)>, pub parens: Option<(Token, Token)>,
pub commas: Vec<Token>,
} }
impl fmt::Display for Params { impl fmt::Display for Params {
@ -3354,6 +3388,7 @@ type RawParams = (
Option<Box<NonDefaultParamSignature>>, Option<Box<NonDefaultParamSignature>>,
Vec<DefaultParamSignature>, Vec<DefaultParamSignature>,
Option<(Token, Token)>, Option<(Token, Token)>,
Vec<Token>,
); );
impl Params { impl Params {
@ -3362,21 +3397,28 @@ impl Params {
var_params: Option<NonDefaultParamSignature>, var_params: Option<NonDefaultParamSignature>,
defaults: Vec<DefaultParamSignature>, defaults: Vec<DefaultParamSignature>,
parens: Option<(Token, Token)>, parens: Option<(Token, Token)>,
commas: Vec<Token>,
) -> Self { ) -> Self {
Self { Self {
non_defaults, non_defaults,
var_params: var_params.map(Box::new), var_params: var_params.map(Box::new),
defaults, defaults,
parens, parens,
commas,
} }
} }
pub fn single(non_default: NonDefaultParamSignature) -> Self {
Self::new(vec![non_default], None, vec![], None, vec![])
}
pub fn deconstruct(self) -> RawParams { pub fn deconstruct(self) -> RawParams {
( (
self.non_defaults, self.non_defaults,
self.var_params, self.var_params,
self.defaults, self.defaults,
self.parens, self.parens,
self.commas,
) )
} }
@ -3522,7 +3564,7 @@ impl LambdaSignature {
pub fn do_sig(do_symbol: &Token) -> Self { pub fn do_sig(do_symbol: &Token) -> Self {
let parens = Some((do_symbol.clone(), do_symbol.clone())); let parens = Some((do_symbol.clone(), do_symbol.clone()));
Self::new( Self::new(
Params::new(vec![], None, vec![], parens), Params::new(vec![], None, vec![], parens, vec![]),
None, None,
TypeBoundSpecs::empty(), TypeBoundSpecs::empty(),
) )

View file

@ -211,7 +211,7 @@ impl Parser {
let mut vars = Vars::empty(); let mut vars = Vars::empty();
match tuple { match tuple {
Tuple::Normal(tup) => { Tuple::Normal(tup) => {
let (pos_args, _var_args, _kw_args, paren) = tup.elems.deconstruct(); let (pos_args, _var_args, _kw_args, paren, _commas) = tup.elems.deconstruct();
for arg in pos_args { for arg in pos_args {
let sig = self let sig = self
.convert_rhs_to_sig(arg.expr) .convert_rhs_to_sig(arg.expr)
@ -321,7 +321,7 @@ impl Parser {
) -> ParseResult<TypeBoundSpecs> { ) -> ParseResult<TypeBoundSpecs> {
debug_call_info!(self); debug_call_info!(self);
let mut bounds = vec![]; let mut bounds = vec![];
let (pos_args, _var_args, _kw_args, _paren) = type_args.args.deconstruct(); let (pos_args, _var_args, _kw_args, _paren, _commas) = type_args.args.deconstruct();
for arg in pos_args.into_iter() { for arg in pos_args.into_iter() {
let bound = self let bound = self
.convert_type_arg_to_bound(arg) .convert_type_arg_to_bound(arg)
@ -357,8 +357,8 @@ impl Parser {
pub(crate) fn convert_args_to_params(&mut self, args: Args) -> ParseResult<Params> { pub(crate) fn convert_args_to_params(&mut self, args: Args) -> ParseResult<Params> {
debug_call_info!(self); debug_call_info!(self);
let (pos_args, var_args, kw_args, parens) = args.deconstruct(); let (pos_args, var_args, kw_args, parens, commas) = args.deconstruct();
let mut params = Params::new(vec![], None, vec![], parens); let mut params = Params::new(vec![], None, vec![], parens, commas);
for (i, arg) in pos_args.into_iter().enumerate() { for (i, arg) in pos_args.into_iter().enumerate() {
let nd_param = self let nd_param = self
.convert_pos_arg_to_non_default_param(arg, i == 0) .convert_pos_arg_to_non_default_param(arg, i == 0)
@ -519,7 +519,7 @@ impl Parser {
for arg in arr.elems.into_iters().0 { for arg in arr.elems.into_iters().0 {
params.push(self.convert_pos_arg_to_non_default_param(arg, false)?); params.push(self.convert_pos_arg_to_non_default_param(arg, false)?);
} }
let params = Params::new(params, None, vec![], None); let params = Params::new(params, None, vec![], None, vec![]);
debug_exit_info!(self); debug_exit_info!(self);
Ok(ParamArrayPattern::new(arr.l_sqbr, params, arr.r_sqbr)) Ok(ParamArrayPattern::new(arr.l_sqbr, params, arr.r_sqbr))
} }
@ -598,7 +598,7 @@ impl Parser {
match tuple { match tuple {
Tuple::Normal(tup) => { Tuple::Normal(tup) => {
let mut params = vec![]; let mut params = vec![];
let (elems, var_args, _, parens) = tup.elems.deconstruct(); let (elems, var_args, _, parens, commas) = tup.elems.deconstruct();
for arg in elems.into_iter() { for arg in elems.into_iter() {
params.push(self.convert_pos_arg_to_non_default_param(arg, false)?); params.push(self.convert_pos_arg_to_non_default_param(arg, false)?);
} }
@ -608,7 +608,7 @@ impl Parser {
} else { } else {
None None
}; };
let params = Params::new(params, var_params, vec![], parens); let params = Params::new(params, var_params, vec![], parens, commas);
debug_exit_info!(self); debug_exit_info!(self);
Ok(ParamTuplePattern::new(params)) Ok(ParamTuplePattern::new(params))
} }
@ -634,14 +634,14 @@ impl Parser {
match rhs { match rhs {
Expr::Literal(lit) => { Expr::Literal(lit) => {
let param = NonDefaultParamSignature::new(ParamPattern::Lit(lit), None); let param = NonDefaultParamSignature::new(ParamPattern::Lit(lit), None);
let params = Params::new(vec![param], None, vec![], None); let params = Params::single(param);
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty())) Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
} }
Expr::Accessor(accessor) => { Expr::Accessor(accessor) => {
let param = self let param = self
.convert_accessor_to_param_sig(accessor) .convert_accessor_to_param_sig(accessor)
.map_err(|_| self.stack_dec(fn_name!()))?; .map_err(|_| self.stack_dec(fn_name!()))?;
let params = Params::new(vec![param], None, vec![], None); let params = Params::single(param);
debug_exit_info!(self); debug_exit_info!(self);
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty())) Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
} }
@ -657,7 +657,7 @@ impl Parser {
.convert_array_to_param_array_pat(array) .convert_array_to_param_array_pat(array)
.map_err(|_| self.stack_dec(fn_name!()))?; .map_err(|_| self.stack_dec(fn_name!()))?;
let param = NonDefaultParamSignature::new(ParamPattern::Array(arr), None); let param = NonDefaultParamSignature::new(ParamPattern::Array(arr), None);
let params = Params::new(vec![param], None, vec![], None); let params = Params::single(param);
debug_exit_info!(self); debug_exit_info!(self);
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty())) Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
} }
@ -666,7 +666,7 @@ impl Parser {
.convert_record_to_param_record_pat(record) .convert_record_to_param_record_pat(record)
.map_err(|_| self.stack_dec(fn_name!()))?; .map_err(|_| self.stack_dec(fn_name!()))?;
let param = NonDefaultParamSignature::new(ParamPattern::Record(rec), None); let param = NonDefaultParamSignature::new(ParamPattern::Record(rec), None);
let params = Params::new(vec![param], None, vec![], None); let params = Params::single(param);
debug_exit_info!(self); debug_exit_info!(self);
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty())) Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
} }
@ -683,7 +683,7 @@ impl Parser {
let param = self let param = self
.convert_rhs_to_param(*exprs.next().unwrap(), false) .convert_rhs_to_param(*exprs.next().unwrap(), false)
.map_err(|_| self.stack_dec(fn_name!()))?; .map_err(|_| self.stack_dec(fn_name!()))?;
let params = Params::new(vec![], Some(param), vec![], None); let params = Params::new(vec![], Some(param), vec![], None, vec![]);
debug_exit_info!(self); debug_exit_info!(self);
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty())) Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
} }
@ -731,8 +731,8 @@ impl Parser {
debug_call_info!(self); debug_call_info!(self);
match tuple { match tuple {
Tuple::Normal(tup) => { Tuple::Normal(tup) => {
let (pos_args, var_args, kw_args, paren) = tup.elems.deconstruct(); let (pos_args, var_args, kw_args, paren, commas) = tup.elems.deconstruct();
let mut params = Params::new(vec![], None, vec![], paren); let mut params = Params::new(vec![], None, vec![], paren, commas);
for (i, arg) in pos_args.into_iter().enumerate() { for (i, arg) in pos_args.into_iter().enumerate() {
let param = self let param = self
.convert_pos_arg_to_non_default_param(arg, i == 0) .convert_pos_arg_to_non_default_param(arg, i == 0)
@ -767,7 +767,7 @@ impl Parser {
.map_err(|_| self.stack_dec(fn_name!()))?; .map_err(|_| self.stack_dec(fn_name!()))?;
debug_exit_info!(self); debug_exit_info!(self);
Ok(LambdaSignature::new( Ok(LambdaSignature::new(
Params::new(vec![sig], None, vec![], None), Params::single(sig),
None, None,
TypeBoundSpecs::empty(), TypeBoundSpecs::empty(),
)) ))

View file

@ -62,7 +62,7 @@ impl Desugarer {
} }
fn desugar_args(mut desugar: impl FnMut(Expr) -> Expr, args: Args) -> Args { fn desugar_args(mut desugar: impl FnMut(Expr) -> Expr, args: Args) -> Args {
let (pos_args, var_args, kw_args, paren) = args.deconstruct(); let (pos_args, var_args, kw_args, paren, commas) = args.deconstruct();
let pos_args = pos_args let pos_args = pos_args
.into_iter() .into_iter()
.map(|arg| PosArg::new(desugar(arg.expr))) .map(|arg| PosArg::new(desugar(arg.expr)))
@ -74,7 +74,7 @@ impl Desugarer {
KwArg::new(arg.keyword, arg.t_spec, desugar(arg.expr)) // TODO: t_spec KwArg::new(arg.keyword, arg.t_spec, desugar(arg.expr)) // TODO: t_spec
}) })
.collect(); .collect();
Args::new(pos_args, var_args, kw_args, paren) Args::new(pos_args, var_args, kw_args, paren, commas)
} }
fn perform_desugar_acc(mut desugar: impl FnMut(Expr) -> Expr, acc: Accessor) -> Accessor { fn perform_desugar_acc(mut desugar: impl FnMut(Expr) -> Expr, acc: Accessor) -> Accessor {
@ -145,12 +145,12 @@ impl Desugarer {
} }
Expr::Array(array) => match array { Expr::Array(array) => match array {
Array::Normal(arr) => { Array::Normal(arr) => {
let (elems, _, _, _) = arr.elems.deconstruct(); let (elems, _, _, _, commas) = arr.elems.deconstruct();
let elems = elems let elems = elems
.into_iter() .into_iter()
.map(|elem| PosArg::new(desugar(elem.expr))) .map(|elem| PosArg::new(desugar(elem.expr)))
.collect(); .collect();
let elems = Args::new(elems, None, vec![], None); let elems = Args::pos_only(elems, None, commas);
let arr = NormalArray::new(arr.l_sqbr, arr.r_sqbr, elems); let arr = NormalArray::new(arr.l_sqbr, arr.r_sqbr, elems);
Expr::Array(Array::Normal(arr)) Expr::Array(Array::Normal(arr))
} }
@ -175,24 +175,24 @@ impl Desugarer {
}, },
Expr::Tuple(tuple) => match tuple { Expr::Tuple(tuple) => match tuple {
Tuple::Normal(tup) => { Tuple::Normal(tup) => {
let (elems, _, _, paren) = tup.elems.deconstruct(); let (elems, _, _, paren, commas) = tup.elems.deconstruct();
let elems = elems let elems = elems
.into_iter() .into_iter()
.map(|elem| PosArg::new(desugar(elem.expr))) .map(|elem| PosArg::new(desugar(elem.expr)))
.collect(); .collect();
let new_tup = Args::new(elems, None, vec![], paren); let new_tup = Args::pos_only(elems, paren, commas);
let tup = NormalTuple::new(new_tup); let tup = NormalTuple::new(new_tup);
Expr::Tuple(Tuple::Normal(tup)) Expr::Tuple(Tuple::Normal(tup))
} }
}, },
Expr::Set(set) => match set { Expr::Set(set) => match set {
astSet::Normal(set) => { astSet::Normal(set) => {
let (elems, _, _, _) = set.elems.deconstruct(); let (elems, _, _, _, commas) = set.elems.deconstruct();
let elems = elems let elems = elems
.into_iter() .into_iter()
.map(|elem| PosArg::new(desugar(elem.expr))) .map(|elem| PosArg::new(desugar(elem.expr)))
.collect(); .collect();
let elems = Args::new(elems, None, vec![], None); let elems = Args::pos_only(elems, None, commas);
let set = NormalSet::new(set.l_brace, set.r_brace, elems); let set = NormalSet::new(set.l_brace, set.r_brace, elems);
Expr::Set(astSet::Normal(set)) Expr::Set(astSet::Normal(set))
} }
@ -359,7 +359,7 @@ impl Desugarer {
)); ));
let param = let param =
NonDefaultParamSignature::new(ParamPattern::VarName(param), None); NonDefaultParamSignature::new(ParamPattern::VarName(param), None);
let params = Params::new(vec![param], None, vec![], None); let params = Params::single(param);
let sig = Signature::Subr(SubrSignature::new( let sig = Signature::Subr(SubrSignature::new(
set! {}, set! {},
name, name,
@ -425,6 +425,7 @@ impl Desugarer {
PosArg::new(Expr::Lambda(second_branch)), PosArg::new(Expr::Lambda(second_branch)),
], ],
None, None,
vec![],
); );
let call = match_symbol.call(args); let call = match_symbol.call(args);
(call, return_t_spec) (call, return_t_spec)
@ -781,7 +782,7 @@ impl Desugarer {
kind: TokenKind::RBrace, kind: TokenKind::RBrace,
..lit.token ..lit.token
}; };
let args = Args::pos_only(vec![PosArg::new(Expr::Literal(lit))], None); let args = Args::single(PosArg::new(Expr::Literal(lit)));
Expr::from(NormalSet::new(l_brace, r_brace, args)) Expr::from(NormalSet::new(l_brace, r_brace, args))
} }
@ -841,7 +842,7 @@ impl Desugarer {
..lit.token ..lit.token
}; };
let t_spec = TypeSpec::enum_t_spec(vec![lit.clone()]); let t_spec = TypeSpec::enum_t_spec(vec![lit.clone()]);
let args = Args::pos_only(vec![PosArg::new(Expr::Literal(lit))], None); let args = Args::single(PosArg::new(Expr::Literal(lit)));
let t_spec_as_expr = Expr::from(NormalSet::new(l_brace, r_brace, args)); let t_spec_as_expr = Expr::from(NormalSet::new(l_brace, r_brace, args));
let t_spec = TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr); let t_spec = TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr);
param.t_spec = Some(t_spec); param.t_spec = Some(t_spec);
@ -879,6 +880,7 @@ impl Desugarer {
let t_spec_as_expr = Expr::from(NormalTuple::new(Args::pos_only( let t_spec_as_expr = Expr::from(NormalTuple::new(Args::pos_only(
ty_exprs, ty_exprs,
tup.elems.parens.clone(), tup.elems.parens.clone(),
tup.elems.commas.clone(),
))); )));
param.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr)); param.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr));
} }
@ -1048,6 +1050,7 @@ impl Desugarer {
let t_spec_as_expr = Expr::from(NormalTuple::new(Args::pos_only( let t_spec_as_expr = Expr::from(NormalTuple::new(Args::pos_only(
ty_exprs, ty_exprs,
tup.elems.parens.clone(), tup.elems.parens.clone(),
tup.elems.commas.clone(),
))); )));
sig.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr)); sig.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr));
} }
@ -1218,10 +1221,7 @@ impl Desugarer {
match acc { match acc {
// x[y] => x.__getitem__(y) // x[y] => x.__getitem__(y)
Accessor::Subscr(subscr) => { Accessor::Subscr(subscr) => {
let args = Args::pos_only( let args = Args::single(PosArg::new(Self::rec_desugar_acc(*subscr.index)));
vec![PosArg::new(Self::rec_desugar_acc(*subscr.index))],
None,
);
let line = subscr.obj.ln_begin().unwrap(); let line = subscr.obj.ln_begin().unwrap();
let call = Call::new( let call = Call::new(
Self::rec_desugar_acc(*subscr.obj), Self::rec_desugar_acc(*subscr.obj),
@ -1236,7 +1236,7 @@ impl Desugarer {
} }
// x.0 => x.__Tuple_getitem__(0) // x.0 => x.__Tuple_getitem__(0)
Accessor::TupleAttr(tattr) => { Accessor::TupleAttr(tattr) => {
let args = Args::pos_only(vec![PosArg::new(Expr::Literal(tattr.index))], None); let args = Args::single(PosArg::new(Expr::Literal(tattr.index)));
let line = tattr.obj.ln_begin().unwrap(); let line = tattr.obj.ln_begin().unwrap();
let call = Call::new( let call = Call::new(
Self::rec_desugar_acc(*tattr.obj), Self::rec_desugar_acc(*tattr.obj),

View file

@ -560,7 +560,7 @@ impl Parser {
let first = self let first = self
.try_reduce_elem() .try_reduce_elem()
.map_err(|_| self.stack_dec(fn_name!()))?; .map_err(|_| self.stack_dec(fn_name!()))?;
let mut elems = Args::pos_only(vec![first], None); let mut elems = Args::single(first);
match self.peek_kind() { match self.peek_kind() {
Some(Semi) => { Some(Semi) => {
self.lpop(); self.lpop();
@ -691,11 +691,15 @@ impl Parser {
Some(RParen) => { Some(RParen) => {
rp = Some(self.lpop()); rp = Some(self.lpop());
debug_exit_info!(self); debug_exit_info!(self);
return Ok(Args::pos_only(vec![], Some((lp.unwrap(), rp.unwrap())))); return Ok(Args::pos_only(
vec![],
Some((lp.unwrap(), rp.unwrap())),
vec![],
));
} }
Some(RBrace | RSqBr | Dedent) => { Some(RBrace | RSqBr | Dedent) => {
debug_exit_info!(self); debug_exit_info!(self);
return Ok(Args::pos_only(vec![], None)); return Ok(Args::empty());
} }
Some(Newline) if style.needs_parens() => { Some(Newline) if style.needs_parens() => {
self.skip(); self.skip();
@ -714,17 +718,17 @@ impl Parser {
expr: Expr::UnaryOp(unary), expr: Expr::UnaryOp(unary),
}) if unary.op.is(PreStar) => { }) if unary.op.is(PreStar) => {
let pos_args = PosArg::new(unary.deconstruct().1); let pos_args = PosArg::new(unary.deconstruct().1);
Args::new(vec![], Some(pos_args), vec![], None) Args::new(vec![], Some(pos_args), vec![], None, vec![])
} }
PosOrKwArg::Pos(PosArg { PosOrKwArg::Pos(PosArg {
expr: Expr::TypeAscription(TypeAscription { expr, t_spec }), expr: Expr::TypeAscription(TypeAscription { expr, t_spec }),
}) if matches!(expr.as_ref(), Expr::UnaryOp(unary) if unary.op.is(PreStar)) => { }) if matches!(expr.as_ref(), Expr::UnaryOp(unary) if unary.op.is(PreStar)) => {
let Expr::UnaryOp(unary) = *expr else { unreachable!() }; let Expr::UnaryOp(unary) = *expr else { unreachable!() };
let var_args = PosArg::new(unary.deconstruct().1.type_asc_expr(t_spec)); let var_args = PosArg::new(unary.deconstruct().1.type_asc_expr(t_spec));
Args::new(vec![], Some(var_args), vec![], None) Args::new(vec![], Some(var_args), vec![], None, vec![])
} }
PosOrKwArg::Pos(arg) => Args::pos_only(vec![arg], None), PosOrKwArg::Pos(arg) => Args::single(arg),
PosOrKwArg::Kw(arg) => Args::new(vec![], None, vec![arg], None), PosOrKwArg::Kw(arg) => Args::new(vec![], None, vec![arg], None, vec![]),
}; };
loop { loop {
match self.peek_kind() { match self.peek_kind() {
@ -750,7 +754,7 @@ impl Parser {
self.skip(); self.skip();
} }
Some(Comma) => { Some(Comma) => {
self.skip(); args.push_comma(self.lpop());
if style.is_colon() || self.cur_is(Comma) { if style.is_colon() || self.cur_is(Comma) {
let err = self.skip_and_throw_syntax_err(caused_by!()); let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err); self.errs.push(err);
@ -767,8 +771,7 @@ impl Parser {
} }
if style.needs_parens() && self.cur_is(RParen) { if style.needs_parens() && self.cur_is(RParen) {
let rp = self.lpop(); let rp = self.lpop();
let (pos_args, var_args, kw_args, _) = args.deconstruct(); args.set_parens((lp.unwrap(), rp));
args = Args::new(pos_args, var_args, kw_args, Some((lp.unwrap(), rp)));
break; break;
} }
if !args.kw_is_empty() { if !args.kw_is_empty() {
@ -807,12 +810,11 @@ impl Parser {
Some(RParen) => { Some(RParen) => {
if let Some(lp) = lp { if let Some(lp) = lp {
let rp = self.lpop(); let rp = self.lpop();
let (pos_args, var_args, kw_args, _) = args.deconstruct(); args.set_parens((lp, rp));
args = Args::new(pos_args, var_args, kw_args, Some((lp, rp)));
} else { } else {
// e.g. f(g 1) // e.g. f(g 1)
let (pos_args, var_args, kw_args, _) = args.deconstruct(); let (pos_args, var_args, kw_args, _, commas) = args.deconstruct();
args = Args::new(pos_args, var_args, kw_args, None); args = Args::new(pos_args, var_args, kw_args, None, commas);
} }
break; break;
} }
@ -830,8 +832,7 @@ impl Parser {
debug_exit_info!(self); debug_exit_info!(self);
return Err(()); return Err(());
} }
let (pos_args, var_args, kw_args, _) = args.deconstruct(); args.set_parens((lp.unwrap(), rp));
args = Args::new(pos_args, var_args, kw_args, Some((lp.unwrap(), rp)));
} }
break; break;
} }
@ -1690,9 +1691,7 @@ impl Parser {
Signature::Var(var) => { Signature::Var(var) => {
let mut last = def.body.block.pop().unwrap(); let mut last = def.body.block.pop().unwrap();
for deco in decos.into_iter() { for deco in decos.into_iter() {
last = deco last = deco.into_expr().call_expr(Args::single(PosArg::new(last)));
.into_expr()
.call_expr(Args::pos_only(vec![PosArg::new(last)], None));
} }
def.body.block.push(last); def.body.block.push(last);
let expr = Expr::Def(Def::new(Signature::Var(var), def.body)); let expr = Expr::Def(Def::new(Signature::Var(var), def.body));
@ -1728,7 +1727,7 @@ impl Parser {
}; };
if self.cur_is(RParen) { if self.cur_is(RParen) {
let rparen = self.lpop(); let rparen = self.lpop();
let args = Args::pos_only(vec![], Some((lparen, rparen))); let args = Args::pos_only(vec![], Some((lparen, rparen)), vec![]);
let unit = Tuple::Normal(NormalTuple::new(args)); let unit = Tuple::Normal(NormalTuple::new(args));
debug_exit_info!(self); debug_exit_info!(self);
return Ok(Expr::Tuple(unit)); return Ok(Expr::Tuple(unit));
@ -2297,7 +2296,7 @@ impl Parser {
len, len,
))); )));
} }
let mut args = Args::pos_only(vec![PosArg::new(first_elem)], None); let mut args = Args::single(PosArg::new(first_elem));
loop { loop {
match self.peek_kind() { match self.peek_kind() {
Some(Comma) => { Some(Comma) => {
@ -2370,7 +2369,7 @@ impl Parser {
expr: Expr::UnaryOp(unary), expr: Expr::UnaryOp(unary),
}) if unary.op.is(PreStar) => { }) if unary.op.is(PreStar) => {
let var_args = Some(PosArg::new(unary.deconstruct().1)); let var_args = Some(PosArg::new(unary.deconstruct().1));
Args::new(vec![], var_args, vec![], None) Args::new(vec![], var_args, vec![], None, vec![])
} }
PosOrKwArg::Pos(PosArg { PosOrKwArg::Pos(PosArg {
expr: Expr::TypeAscription(TypeAscription { expr, t_spec }), expr: Expr::TypeAscription(TypeAscription { expr, t_spec }),
@ -2378,10 +2377,10 @@ impl Parser {
let Expr::UnaryOp(unary) = *expr else { unreachable!() }; let Expr::UnaryOp(unary) = *expr else { unreachable!() };
let expr = unary.deconstruct().1; let expr = unary.deconstruct().1;
let var_args = Some(PosArg::new(expr.type_asc_expr(t_spec))); let var_args = Some(PosArg::new(expr.type_asc_expr(t_spec)));
Args::new(vec![], var_args, vec![], None) Args::new(vec![], var_args, vec![], None, vec![])
} }
PosOrKwArg::Pos(pos) => Args::pos_only(vec![pos], None), PosOrKwArg::Pos(pos) => Args::single(pos),
PosOrKwArg::Kw(kw) => Args::new(vec![], None, vec![kw], None), PosOrKwArg::Kw(kw) => Args::new(vec![], None, vec![kw], None, vec![]),
}; };
#[allow(clippy::while_let_loop)] #[allow(clippy::while_let_loop)]
loop { loop {
@ -2502,11 +2501,7 @@ impl Parser {
mid_expr.ln_begin().unwrap(), mid_expr.ln_begin().unwrap(),
mid_expr.col_begin().unwrap(), mid_expr.col_begin().unwrap(),
); );
let call = Call::new( let call = Call::new(str_func, None, Args::single(PosArg::new(mid_expr)));
str_func,
None,
Args::pos_only(vec![PosArg::new(mid_expr)], None),
);
let op = Token::new( let op = Token::new(
Plus, Plus,
"+", "+",

View file

@ -16,13 +16,13 @@ impl Parser {
} }
Expr::Array(array) => match array { Expr::Array(array) => match array {
Array::Normal(arr) => { Array::Normal(arr) => {
let (elems, ..) = arr.elems.deconstruct(); let (elems, .., commas) = arr.elems.deconstruct();
let mut const_elems = vec![]; let mut const_elems = vec![];
for elem in elems.into_iter() { for elem in elems.into_iter() {
let const_expr = Self::validate_const_expr(elem.expr)?; let const_expr = Self::validate_const_expr(elem.expr)?;
const_elems.push(ConstPosArg::new(const_expr)); const_elems.push(ConstPosArg::new(const_expr));
} }
let elems = ConstArgs::new(const_elems, None, vec![], None); let elems = ConstArgs::pos_only(const_elems, None, commas);
let const_arr = ConstArray::new(arr.l_sqbr, arr.r_sqbr, elems, None); let const_arr = ConstArray::new(arr.l_sqbr, arr.r_sqbr, elems, None);
Ok(ConstExpr::Array(const_arr)) Ok(ConstExpr::Array(const_arr))
} }
@ -34,13 +34,13 @@ impl Parser {
}, },
Expr::Set(set) => match set { Expr::Set(set) => match set {
Set::Normal(set) => { Set::Normal(set) => {
let (elems, ..) = set.elems.deconstruct(); let (elems, .., commas) = set.elems.deconstruct();
let mut const_elems = vec![]; let mut const_elems = vec![];
for elem in elems.into_iter() { for elem in elems.into_iter() {
let const_expr = Self::validate_const_expr(elem.expr)?; let const_expr = Self::validate_const_expr(elem.expr)?;
const_elems.push(ConstPosArg::new(const_expr)); const_elems.push(ConstPosArg::new(const_expr));
} }
let elems = ConstArgs::new(const_elems, None, vec![], None); let elems = ConstArgs::pos_only(const_elems, None, commas);
let const_set = ConstSet::new(set.l_brace, set.r_brace, elems); let const_set = ConstSet::new(set.l_brace, set.r_brace, elems);
Ok(ConstExpr::Set(const_set)) Ok(ConstExpr::Set(const_set))
} }
@ -69,13 +69,13 @@ impl Parser {
}, },
Expr::Tuple(tuple) => match tuple { Expr::Tuple(tuple) => match tuple {
Tuple::Normal(tup) => { Tuple::Normal(tup) => {
let (elems, _, _, paren) = tup.elems.deconstruct(); let (elems, _, _, paren, commas) = tup.elems.deconstruct();
let mut const_elems = vec![]; let mut const_elems = vec![];
for elem in elems.into_iter() { for elem in elems.into_iter() {
let const_expr = Self::validate_const_expr(elem.expr)?; let const_expr = Self::validate_const_expr(elem.expr)?;
const_elems.push(ConstPosArg::new(const_expr)); const_elems.push(ConstPosArg::new(const_expr));
} }
let elems = ConstArgs::pos_only(const_elems, paren); let elems = ConstArgs::pos_only(const_elems, paren, commas);
let const_tup = ConstTuple::new(elems); let const_tup = ConstTuple::new(elems);
Ok(ConstExpr::Tuple(const_tup)) Ok(ConstExpr::Tuple(const_tup))
} }
@ -100,13 +100,13 @@ impl Parser {
"complex const function call", "complex const function call",
)); ));
}; };
let (pos_args, _, _, paren) = call.args.deconstruct(); let (pos_args, _, _, paren, commas) = call.args.deconstruct();
let mut const_pos_args = vec![]; let mut const_pos_args = vec![];
for elem in pos_args.into_iter() { for elem in pos_args.into_iter() {
let const_expr = Self::validate_const_expr(elem.expr)?; let const_expr = Self::validate_const_expr(elem.expr)?;
const_pos_args.push(ConstPosArg::new(const_expr)); const_pos_args.push(ConstPosArg::new(const_expr));
} }
let args = ConstArgs::pos_only(const_pos_args, paren); let args = ConstArgs::pos_only(const_pos_args, paren, commas);
Ok(ConstExpr::App(ConstApp::new(acc, args))) Ok(ConstExpr::App(ConstApp::new(acc, args)))
} }
Expr::Def(def) => Self::validate_const_def(def).map(ConstExpr::Def), Expr::Def(def) => Self::validate_const_def(def).map(ConstExpr::Def),
@ -194,7 +194,7 @@ impl Parser {
fn call_to_predecl_type_spec(call: Call) -> Result<PreDeclTypeSpec, ParseError> { fn call_to_predecl_type_spec(call: Call) -> Result<PreDeclTypeSpec, ParseError> {
match *call.obj { match *call.obj {
Expr::Accessor(Accessor::Ident(ident)) => { Expr::Accessor(Accessor::Ident(ident)) => {
let (_pos_args, _var_args, _kw_args, paren) = call.args.deconstruct(); let (_pos_args, _var_args, _kw_args, paren, commas) = call.args.deconstruct();
let mut pos_args = vec![]; let mut pos_args = vec![];
for arg in _pos_args.into_iter() { for arg in _pos_args.into_iter() {
let const_expr = Self::validate_const_expr(arg.expr)?; let const_expr = Self::validate_const_expr(arg.expr)?;
@ -213,7 +213,7 @@ impl Parser {
} }
Ok(PreDeclTypeSpec::Simple(SimpleTypeSpec::new( Ok(PreDeclTypeSpec::Simple(SimpleTypeSpec::new(
ident, ident,
ConstArgs::new(pos_args, var_args, kw_args, paren), ConstArgs::new(pos_args, var_args, kw_args, paren, commas),
))) )))
} }
_ => todo!(), _ => todo!(),
@ -309,12 +309,12 @@ impl Parser {
match set { match set {
Set::Normal(set) => { Set::Normal(set) => {
let mut elem_ts = vec![]; let mut elem_ts = vec![];
let (elems, .., paren) = set.elems.deconstruct(); let (elems, .., paren, commas) = set.elems.deconstruct();
for elem in elems.into_iter() { for elem in elems.into_iter() {
let const_expr = Self::validate_const_expr(elem.expr)?; let const_expr = Self::validate_const_expr(elem.expr)?;
elem_ts.push(ConstPosArg::new(const_expr)); elem_ts.push(ConstPosArg::new(const_expr));
} }
Ok(TypeSpec::Enum(ConstArgs::pos_only(elem_ts, paren))) Ok(TypeSpec::Enum(ConstArgs::pos_only(elem_ts, paren, commas)))
} }
Set::WithLength(set) => { Set::WithLength(set) => {
let t_spec = Self::expr_to_type_spec(set.elem.expr)?; let t_spec = Self::expr_to_type_spec(set.elem.expr)?;
@ -375,7 +375,7 @@ impl Parser {
match tuple { match tuple {
Tuple::Normal(tup) => { Tuple::Normal(tup) => {
let mut tup_spec = vec![]; let mut tup_spec = vec![];
let (elems, .., parens) = tup.elems.deconstruct(); let (elems, .., parens, _commas) = tup.elems.deconstruct();
for elem in elems.into_iter() { for elem in elems.into_iter() {
let value = Self::expr_to_type_spec(elem.expr)?; let value = Self::expr_to_type_spec(elem.expr)?;
tup_spec.push(value); tup_spec.push(value);