mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-27 11:59:05 +00:00
chore(els): improve signature help
This commit is contained in:
parent
e6b7e65d93
commit
1aa83f140a
26 changed files with 475 additions and 334 deletions
|
@ -11,7 +11,7 @@ use erg_compiler::hir::Expr;
|
|||
|
||||
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;
|
||||
|
||||
impl<Checker: BuildRunnable> Server<Checker> {
|
||||
|
@ -25,11 +25,11 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
let diag = diags.remove(0);
|
||||
let mut map = HashMap::new();
|
||||
let Some(visitor) = self.get_visitor(&uri) else {
|
||||
Self::send_log("visitor not found")?;
|
||||
send_log("visitor not found")?;
|
||||
return Ok(None);
|
||||
};
|
||||
let Some(artifact) = self.artifacts.get(&uri) else {
|
||||
Self::send_log("artifact not found")?;
|
||||
send_log("artifact not found")?;
|
||||
return Ok(None);
|
||||
};
|
||||
let warns = artifact
|
||||
|
@ -45,7 +45,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
match visitor.get_min_expr(&token) {
|
||||
Some(Expr::Def(def)) => {
|
||||
let Some(mut range) = util::loc_to_range(def.loc()) else {
|
||||
Self::send_log("range not found")?;
|
||||
send_log("range not found")?;
|
||||
continue;
|
||||
};
|
||||
let next = lsp_types::Range {
|
||||
|
@ -67,7 +67,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
}
|
||||
Some(";") => range.end.character += 1,
|
||||
Some(other) => {
|
||||
Self::send_log(format!("? {other}"))?;
|
||||
send_log(format!("? {other}"))?;
|
||||
}
|
||||
}
|
||||
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<()> {
|
||||
Self::send_log(format!("code action requested: {msg}"))?;
|
||||
send_log(format!("code action requested: {msg}"))?;
|
||||
let params = CodeActionParams::deserialize(&msg["params"])?;
|
||||
let result = match params
|
||||
.context
|
||||
|
@ -172,12 +172,10 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
Some("quickfix") => self.send_quick_fix(msg, params)?,
|
||||
None => self.send_normal_action(msg, params)?,
|
||||
Some(other) => {
|
||||
Self::send_log(&format!("Unknown code action requested: {other}"))?;
|
||||
send_log(&format!("Unknown code action requested: {other}"))?;
|
||||
vec![]
|
||||
}
|
||||
};
|
||||
Self::send(
|
||||
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }),
|
||||
)
|
||||
send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,12 +7,12 @@ use erg_compiler::hir::Expr;
|
|||
|
||||
use lsp_types::{CodeLens, CodeLensParams, Url};
|
||||
|
||||
use crate::server::{ELSResult, Server};
|
||||
use crate::server::{send, send_log, ELSResult, Server};
|
||||
use crate::util;
|
||||
|
||||
impl<Checker: BuildRunnable> Server<Checker> {
|
||||
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 uri = util::normalize_url(params.text_document.uri);
|
||||
// TODO: parallelize
|
||||
|
@ -21,9 +21,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
self.send_class_inherits_lens(&uri)?,
|
||||
]
|
||||
.concat();
|
||||
Self::send(
|
||||
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }),
|
||||
)
|
||||
send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }))
|
||||
}
|
||||
|
||||
fn send_trait_impls_lens(&mut self, uri: &Url) -> ELSResult<Vec<CodeLens>> {
|
||||
|
|
|
@ -9,18 +9,18 @@ use erg_compiler::hir::Expr;
|
|||
|
||||
use lsp_types::{ExecuteCommandParams, Location, Url};
|
||||
|
||||
use crate::server::{ELSResult, Server};
|
||||
use crate::server::{send, send_log, ELSResult, Server};
|
||||
use crate::util;
|
||||
|
||||
impl<Checker: BuildRunnable> Server<Checker> {
|
||||
pub(crate) fn execute_command(&mut self, msg: &Value) -> ELSResult<()> {
|
||||
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)]
|
||||
match ¶ms.command[..] {
|
||||
other => {
|
||||
Self::send_log(format!("unknown command: {other}"))?;
|
||||
Self::send(
|
||||
send_log(format!("unknown command: {other}"))?;
|
||||
send(
|
||||
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": Value::Null }),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ use lsp_types::{
|
|||
MarkupContent, MarkupKind,
|
||||
};
|
||||
|
||||
use crate::server::{ELSResult, Server};
|
||||
use crate::server::{send, send_log, ELSResult, Server};
|
||||
use crate::util;
|
||||
|
||||
fn mark_to_string(mark: MarkedString) -> String {
|
||||
|
@ -70,7 +70,7 @@ impl CompletionOrder {
|
|||
|
||||
impl<Checker: BuildRunnable> Server<Checker> {
|
||||
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 uri = util::normalize_url(params.text_document_position.text_document.uri);
|
||||
let path = util::uri_to_path(&uri);
|
||||
|
@ -84,7 +84,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
Some(":") => AccessKind::Attr, // or type ascription
|
||||
_ => AccessKind::Name,
|
||||
};
|
||||
Self::send_log(format!("AccessKind: {acc_kind:?}"))?;
|
||||
send_log(format!("AccessKind: {acc_kind:?}"))?;
|
||||
let mut result: Vec<CompletionItem> = vec![];
|
||||
let contexts = if acc_kind.is_local() {
|
||||
let prev_token = self.file_cache.get_token_relatively(&uri, pos, -1)?;
|
||||
|
@ -101,7 +101,6 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
} else {
|
||||
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()) {
|
||||
if acc_kind.is_attr() && vi.vis.is_private() {
|
||||
continue;
|
||||
|
@ -147,19 +146,17 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
item.data = Some(Value::String(vi.def_loc.to_string()));
|
||||
result.push(item);
|
||||
}
|
||||
Self::send_log(format!("completion items: {}", result.len()))?;
|
||||
Self::send(
|
||||
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }),
|
||||
)
|
||||
send_log(format!("completion items: {}", result.len()))?;
|
||||
send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }))
|
||||
}
|
||||
|
||||
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"])?;
|
||||
if let Some(data) = &item.data {
|
||||
let mut contents = vec![];
|
||||
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)?;
|
||||
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"),
|
||||
}));
|
||||
}
|
||||
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 }))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use erg_compiler::varinfo::VarInfo;
|
|||
|
||||
use lsp_types::{GotoDefinitionParams, GotoDefinitionResponse, Url};
|
||||
|
||||
use crate::server::{ELSResult, Server};
|
||||
use crate::server::{send, send_log, ELSResult, Server};
|
||||
use crate::util;
|
||||
|
||||
impl<Checker: BuildRunnable> Server<Checker> {
|
||||
|
@ -18,18 +18,18 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
token: &Token,
|
||||
) -> ELSResult<Option<VarInfo>> {
|
||||
if !token.category_is(TokenCategory::Symbol) {
|
||||
Self::send_log(format!("not symbol: {token}"))?;
|
||||
send_log(format!("not symbol: {token}"))?;
|
||||
Ok(None)
|
||||
} else if let Some(visitor) = self.get_visitor(uri) {
|
||||
Ok(visitor.get_info(token))
|
||||
} else {
|
||||
Self::send_log("not found")?;
|
||||
send_log("not found")?;
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
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 uri = util::normalize_url(params.text_document_position_params.text_document.uri);
|
||||
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)) {
|
||||
(Some(path), Some(range)) => {
|
||||
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(
|
||||
def_uri, range,
|
||||
)])
|
||||
}
|
||||
_ => {
|
||||
Self::send_log("not found (maybe builtin)")?;
|
||||
send_log("not found (maybe builtin)")?;
|
||||
GotoDefinitionResponse::Array(vec![])
|
||||
}
|
||||
}
|
||||
|
@ -52,11 +52,9 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
GotoDefinitionResponse::Array(vec![])
|
||||
}
|
||||
} else {
|
||||
Self::send_log("lex error occurred")?;
|
||||
send_log("lex error occurred")?;
|
||||
GotoDefinitionResponse::Array(vec![])
|
||||
};
|
||||
Self::send(
|
||||
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }),
|
||||
)
|
||||
send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@ use erg_compiler::error::CompileErrors;
|
|||
|
||||
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;
|
||||
|
||||
impl<Checker: BuildRunnable> Server<Checker> {
|
||||
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 mode = if path.to_string_lossy().ends_with(".d.er") {
|
||||
"declare"
|
||||
|
@ -27,19 +27,19 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
};
|
||||
match checker.build(code.into(), mode) {
|
||||
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());
|
||||
// clear previous diagnostics
|
||||
self.send_diagnostics(uri.clone(), vec![])?;
|
||||
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.artifacts.insert(uri.clone(), artifact.into());
|
||||
}
|
||||
Err(artifact) => {
|
||||
Self::send_log(format!("found errors: {}", artifact.errors.len()))?;
|
||||
Self::send_log(format!("found warns: {}", artifact.warns.len()))?;
|
||||
send_log(format!("found errors: {}", artifact.errors.len()))?;
|
||||
send_log(format!("found warns: {}", artifact.warns.len()))?;
|
||||
let diags = artifact
|
||||
.errors
|
||||
.clone()
|
||||
|
@ -51,14 +51,14 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
self.send_diagnostics(uri.clone(), vec![])?;
|
||||
}
|
||||
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.artifacts.insert(uri.clone(), artifact);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
let dependents = self.dependents_of(&uri);
|
||||
|
@ -132,13 +132,13 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
.map(|doc| doc.publish_diagnostics.is_some())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
Self::send(&json!({
|
||||
send(&json!({
|
||||
"jsonrpc": "2.0",
|
||||
"method": "textDocument/publishDiagnostics",
|
||||
"params": params,
|
||||
}))?;
|
||||
} else {
|
||||
Self::send_log("the client does not support diagnostics")?;
|
||||
send_log("the client does not support diagnostics")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use erg_compiler::varinfo::AbsLocation;
|
|||
|
||||
use lsp_types::{HoverContents, HoverParams, MarkedString, Url};
|
||||
|
||||
use crate::server::{ELSResult, Server};
|
||||
use crate::server::{send, send_log, ELSResult, Server};
|
||||
use crate::util;
|
||||
|
||||
const PROG_LANG: &str = if cfg!(feature = "py_compatible") {
|
||||
|
@ -99,7 +99,7 @@ macro_rules! next {
|
|||
|
||||
impl<Checker: BuildRunnable> Server<Checker> {
|
||||
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 uri = util::normalize_url(params.text_document_position_params.text_document.uri);
|
||||
let pos = params.text_document_position_params.position;
|
||||
|
@ -184,12 +184,10 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
Self::send_log("lex error")?;
|
||||
send_log("lex error")?;
|
||||
}
|
||||
let result = json!({ "contents": HoverContents::Array(sort_hovers(contents)) });
|
||||
Self::send(
|
||||
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }),
|
||||
)
|
||||
send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }))
|
||||
}
|
||||
|
||||
pub(crate) fn show_doc_comment(
|
||||
|
|
|
@ -15,7 +15,7 @@ use erg_compiler::artifact::{BuildRunnable, IncompleteArtifact};
|
|||
use erg_compiler::hir::{Block, Call, ClassDef, Def, Expr, Lambda, Params, PatchDef, Signature};
|
||||
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::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> {
|
||||
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 uri = util::normalize_url(params.text_document.uri);
|
||||
let mut result = vec![];
|
||||
|
@ -102,9 +102,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
result.extend(self.get_expr_hint(chunk));
|
||||
}
|
||||
}
|
||||
Self::send(
|
||||
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }),
|
||||
)
|
||||
send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }))
|
||||
}
|
||||
|
||||
fn get_expr_hint(&self, expr: &Expr) -> Vec<InlayHint> {
|
||||
|
|
|
@ -7,7 +7,7 @@ use erg_compiler::varinfo::AbsLocation;
|
|||
|
||||
use lsp_types::{Position, ReferenceParams, Url};
|
||||
|
||||
use crate::server::{ELSResult, Server};
|
||||
use crate::server::{send, ELSResult, Server};
|
||||
use crate::util;
|
||||
|
||||
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 pos = params.text_document_position.position;
|
||||
let result = self.show_refs_inner(&uri, pos);
|
||||
Self::send(
|
||||
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }),
|
||||
)
|
||||
send(&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> {
|
||||
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(vi) = visitor.get_info(&tok) {
|
||||
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> {
|
||||
let mut refs = vec![];
|
||||
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() {
|
||||
if let (Some(path), Some(range)) =
|
||||
(&referrer.module, util::loc_to_range(referrer.loc))
|
||||
|
|
|
@ -20,17 +20,17 @@ use lsp_types::{
|
|||
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;
|
||||
|
||||
impl<Checker: BuildRunnable> Server<Checker> {
|
||||
pub(crate) fn rename(&mut self, msg: &Value) -> ELSResult<()> {
|
||||
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 pos = params.text_document_position.position;
|
||||
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(vi) = visitor.get_info(&tok) {
|
||||
let mut changes: HashMap<Url, Vec<TextEdit>> = HashMap::new();
|
||||
|
@ -61,14 +61,14 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
_ => format!("this {kind} cannot be renamed"),
|
||||
};
|
||||
let edit = WorkspaceEdit::new(changes);
|
||||
Self::send(
|
||||
send(
|
||||
&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());
|
||||
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() {
|
||||
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 edit = WorkspaceEdit::new(changes);
|
||||
Self::send(
|
||||
send(
|
||||
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": edit }),
|
||||
)?;
|
||||
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(×tamps) {
|
||||
break;
|
||||
}
|
||||
|
@ -99,9 +99,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
}
|
||||
}
|
||||
}
|
||||
Self::send(
|
||||
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": Value::Null }),
|
||||
)
|
||||
send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": Value::Null }))
|
||||
}
|
||||
|
||||
fn commit_change(
|
||||
|
@ -269,7 +267,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
}
|
||||
|
||||
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 mut edits = HashMap::new();
|
||||
let mut renames = vec![];
|
||||
|
@ -307,6 +305,6 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
document_changes: Some(changes),
|
||||
..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 }))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ use erg_compiler::ASTBuilder;
|
|||
|
||||
use lsp_types::{SemanticTokenType, SemanticTokens, SemanticTokensParams};
|
||||
|
||||
use crate::server::{ELSResult, Server};
|
||||
use crate::server::{send, send_log, ELSResult, Server};
|
||||
use crate::util;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -284,7 +284,7 @@ impl ASTSemanticState {
|
|||
|
||||
impl<Checker: BuildRunnable> Server<Checker> {
|
||||
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 uri = util::normalize_url(params.text_document.uri);
|
||||
let path = util::uri_to_path(&uri);
|
||||
|
@ -298,8 +298,6 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
}
|
||||
Err(_) => json!(null),
|
||||
};
|
||||
Self::send(
|
||||
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }),
|
||||
)
|
||||
send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ use erg_common::normalize_path;
|
|||
use erg_compiler::artifact::{BuildRunnable, IncompleteArtifact};
|
||||
use erg_compiler::build_hir::HIRBuilder;
|
||||
use erg_compiler::context::{Context, ModuleContext};
|
||||
use erg_compiler::hir::Expr;
|
||||
use erg_compiler::module::{SharedCompilerResource, SharedModuleIndex};
|
||||
use erg_compiler::ty::HasType;
|
||||
|
||||
|
@ -71,7 +72,7 @@ impl From<&str> for ELSFeatures {
|
|||
|
||||
macro_rules! _log {
|
||||
($($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.
|
||||
#[derive(Debug)]
|
||||
pub struct Server<Checker: BuildRunnable = HIRBuilder> {
|
||||
|
@ -120,7 +149,8 @@ pub struct Server<Checker: BuildRunnable = HIRBuilder> {
|
|||
pub(crate) file_cache: FileCache,
|
||||
pub(crate) modules: Dict<Url, ModuleContext>,
|
||||
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> {
|
||||
|
@ -133,6 +163,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
file_cache: FileCache::new(),
|
||||
modules: Dict::new(),
|
||||
artifacts: Dict::new(),
|
||||
current_sig: None,
|
||||
_checker: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
@ -155,11 +186,11 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
|
||||
#[allow(clippy::field_reassign_with_default)]
|
||||
fn init(&mut self, msg: &Value, id: i64) -> ELSResult<()> {
|
||||
Self::send_log("initializing ELS")?;
|
||||
send_log("initializing ELS")?;
|
||||
// #[allow(clippy::collapsible_if)]
|
||||
if msg.get("params").is_some() && msg["params"].get("capabilities").is_some() {
|
||||
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 disabled_features = vec![];
|
||||
|
@ -247,7 +278,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
result.capabilities.code_lens_provider = Some(CodeLensOptions {
|
||||
resolve_provider: Some(false),
|
||||
});
|
||||
Self::send(&json!({
|
||||
send(&json!({
|
||||
"jsonrpc": "2.0",
|
||||
"id": id,
|
||||
"result": result,
|
||||
|
@ -255,13 +286,13 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
}
|
||||
|
||||
fn exit(&self) -> ELSResult<()> {
|
||||
Self::send_log("exiting ELS")?;
|
||||
send_log("exiting ELS")?;
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
fn shutdown(&self, id: i64) -> ELSResult<()> {
|
||||
Self::send_log("shutting down ELS")?;
|
||||
Self::send(&json!({
|
||||
send_log("shutting down ELS")?;
|
||||
send(&json!({
|
||||
"jsonrpc": "2.0",
|
||||
"id": id,
|
||||
"result": json!(null),
|
||||
|
@ -346,7 +377,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
Ok(())
|
||||
}
|
||||
(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),
|
||||
"workspace/willRenameFiles" => self.rename_files(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<()> {
|
||||
match method {
|
||||
"initialized" => Self::send_log("successfully bound"),
|
||||
"initialized" => send_log("successfully bound"),
|
||||
"exit" => self.exit(),
|
||||
"textDocument/didOpen" => {
|
||||
let uri = util::parse_and_normalize_url(
|
||||
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();
|
||||
self.file_cache.update(&uri, code.to_string());
|
||||
self.check_file(uri, code)
|
||||
|
@ -388,49 +419,21 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
let uri = util::parse_and_normalize_url(
|
||||
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)?;
|
||||
self.clear_cache(&uri);
|
||||
self.check_file(uri, &code)
|
||||
}
|
||||
"textDocument/didChange" => {
|
||||
let params = DidChangeTextDocumentParams::deserialize(msg["params"].clone())?;
|
||||
// Self::send_log(format!("{method}: {params:?}"))?;
|
||||
self.file_cache.incremental_update(params);
|
||||
send_log("file cache updated")?;
|
||||
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> {
|
||||
self.artifacts
|
||||
.get(uri)?
|
||||
|
@ -440,7 +443,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
}
|
||||
|
||||
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![];
|
||||
if let Some(visitor) = self.get_visitor(uri) {
|
||||
let ns = visitor.get_namespace(pos);
|
||||
|
@ -467,7 +470,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
.file_cache
|
||||
.get_token_relatively(uri, attr_marker_pos, -2)?;
|
||||
if let Some(token) = maybe_token {
|
||||
Self::send_log(format!("token: {token}"))?;
|
||||
// send_log(format!("token: {token}"))?;
|
||||
let mut ctxs = vec![];
|
||||
if let Some(visitor) = self.get_visitor(uri) {
|
||||
if let Some(expr) = visitor.get_min_expr(&token) {
|
||||
|
@ -482,11 +485,13 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
{
|
||||
ctxs.push(singular_ctx);
|
||||
}
|
||||
} else {
|
||||
send_log("expr not found: {token}")?;
|
||||
}
|
||||
}
|
||||
Ok(ctxs)
|
||||
} else {
|
||||
Self::send_log("token not found")?;
|
||||
send_log("token not found")?;
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
use erg_common::traits::NoTypeDisplay;
|
||||
use erg_compiler::ty::HasType;
|
||||
use lsp_types::Position;
|
||||
use serde::Deserialize;
|
||||
use serde_json::json;
|
||||
use serde_json::Value;
|
||||
|
||||
use erg_common::traits::{DequeStream, Locational, NoTypeDisplay};
|
||||
use erg_compiler::artifact::BuildRunnable;
|
||||
use erg_compiler::erg_parser::token::{Token, TokenKind};
|
||||
use erg_compiler::hir::Expr;
|
||||
use erg_compiler::ty::{HasType, ParamTy};
|
||||
|
||||
use lsp_types::{
|
||||
ParameterInformation, ParameterLabel, SignatureHelp, SignatureHelpParams, SignatureInformation,
|
||||
Url,
|
||||
ParameterInformation, ParameterLabel, Position, SignatureHelp, SignatureHelpContext,
|
||||
SignatureHelpParams, SignatureHelpTriggerKind, SignatureInformation, Url,
|
||||
};
|
||||
|
||||
use crate::server::{ELSResult, Server};
|
||||
use crate::server::{send, send_log, ELSResult, Server};
|
||||
use crate::util;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
|
@ -26,7 +26,7 @@ pub enum Trigger {
|
|||
impl From<String> for Trigger {
|
||||
fn from(s: String) -> Self {
|
||||
match s.as_str() {
|
||||
"(" | ")" => Trigger::Paren,
|
||||
"(" => Trigger::Paren,
|
||||
"," => Trigger::Comma,
|
||||
"|" => Trigger::VBar,
|
||||
_ => 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> {
|
||||
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 uri = util::normalize_url(params.text_document_position_params.text_document.uri);
|
||||
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
|
||||
.context
|
||||
.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::VBar) | None => None,
|
||||
};
|
||||
Self::send(
|
||||
&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }),
|
||||
)
|
||||
send(&json!({ "jsonrpc": "2.0", "id": msg["id"].as_i64().unwrap(), "result": result }))
|
||||
}
|
||||
|
||||
fn get_first_help(&self, uri: &Url, pos: Position) -> Option<SignatureHelp> {
|
||||
if let Some(token) = self.file_cache.get_token_relatively(uri, pos, -1).ok()? {
|
||||
fn nth(&self, uri: &Url, args_loc: erg_common::error::Location, token: &Token) -> usize {
|
||||
// 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) {
|
||||
match visitor.get_min_expr(&token) {
|
||||
Some(Expr::Call(call)) => {
|
||||
let sig_t = call.signature_t().unwrap();
|
||||
Self::send_log(format!("t: {sig_t}")).unwrap();
|
||||
Some(Expr::Call(_call)) => {
|
||||
// let sig_t = call.signature_t().unwrap();
|
||||
// send_log(format!("call: {call}")).unwrap();
|
||||
}
|
||||
Some(Expr::Accessor(acc)) => {
|
||||
let sig_t = acc.ref_t();
|
||||
return self.make_sig_help(acc, 0);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
send_log("lex error occurred").unwrap();
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn get_continuous_help(&mut self, uri: &Url, pos: Position) -> Option<SignatureHelp> {
|
||||
if let Some(comma) = self.file_cache.get_token_relatively(uri, pos, -1).ok()? {
|
||||
send_log(format!("comma: {comma}")).unwrap();
|
||||
if let Some(visitor) = self.get_visitor(uri) {
|
||||
#[allow(clippy::single_match)]
|
||||
match visitor.get_min_expr(&comma) {
|
||||
Some(Expr::Call(call)) => {
|
||||
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 {
|
||||
send_log("lex error occurred").unwrap();
|
||||
}
|
||||
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::Simple(
|
||||
nd_param.name().map_or("".to_string(), |s| s.to_string()),
|
||||
),
|
||||
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::Simple(
|
||||
var_params.name().map_or("".to_string(), |s| s.to_string()),
|
||||
),
|
||||
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: format!("{}: {sig_t}", acc.to_string_notype()),
|
||||
label,
|
||||
documentation: None,
|
||||
parameters: Some(parameters),
|
||||
active_parameter: Some(0),
|
||||
active_parameter: Some(nth),
|
||||
};
|
||||
return Some(SignatureHelp {
|
||||
Some(SignatureHelp {
|
||||
signatures: vec![info],
|
||||
active_parameter: None,
|
||||
active_signature: None,
|
||||
});
|
||||
}
|
||||
Some(other) => {
|
||||
Self::send_log(format!("other: {other}")).unwrap();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Self::send_log("lex error occurred").unwrap();
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn get_continuous_help(&self, uri: &Url, pos: Position) -> Option<SignatureHelp> {
|
||||
if let Some(token) = self.file_cache.get_token(uri, pos) {
|
||||
Self::send_log(format!("comma?: {token}")).unwrap();
|
||||
if let Some(visitor) = self.get_visitor(uri) {
|
||||
#[allow(clippy::single_match)]
|
||||
match visitor.get_min_expr(&token) {
|
||||
Some(Expr::Call(call)) => {
|
||||
Self::send_log(format!("call: {call}")).unwrap();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Self::send_log("lex error occurred").unwrap();
|
||||
}
|
||||
None
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,10 @@ pub fn loc_to_pos(loc: erg_common::error::Location) -> Option<Position> {
|
|||
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 {
|
||||
let ln_begin = loc.ln_begin().unwrap_or(0);
|
||||
let ln_end = loc.ln_end().unwrap_or(0);
|
||||
|
|
|
@ -2799,13 +2799,10 @@ impl PyCodeGenerator {
|
|||
erg_parser::ast::NonDefaultParamSignature::new(ParamPattern::VarName(param), None);
|
||||
let vi = VarInfo::parameter(new_first_param.typ().clone(), ident.vi.def_loc.clone());
|
||||
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)
|
||||
} else {
|
||||
(
|
||||
"_".into(),
|
||||
Params::new(vec![self_param], None, vec![], None),
|
||||
)
|
||||
("_".into(), Params::single(self_param))
|
||||
};
|
||||
let bounds = TypeBoundSpecs::empty();
|
||||
let subr_sig = SubrSignature::new(ident, bounds, params, sig.t_spec().cloned());
|
||||
|
@ -2883,22 +2880,22 @@ impl PyCodeGenerator {
|
|||
let raw =
|
||||
erg_parser::ast::NonDefaultParamSignature::new(ParamPattern::VarName(param), 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 sig = SubrSignature::new(ident, bounds, params, sig.t_spec().cloned());
|
||||
let arg = PosArg::new(Expr::Accessor(Accessor::private_with_line(
|
||||
Str::from(param_name),
|
||||
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 body = DefBody::new(EQUAL, block, DefId(0));
|
||||
self.emit_subr_def(Some(class_ident.inspect()), sig, body);
|
||||
} else {
|
||||
let params = Params::new(vec![], None, vec![], None);
|
||||
let params = Params::empty();
|
||||
let bounds = TypeBoundSpecs::empty();
|
||||
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 body = DefBody::new(EQUAL, block, DefId(0));
|
||||
self.emit_subr_def(Some(class_ident.inspect()), sig, body);
|
||||
|
|
|
@ -947,7 +947,7 @@ impl Context {
|
|||
)?;
|
||||
let op = hir::Expr::Accessor(hir::Accessor::private(symbol, t));
|
||||
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 {
|
||||
return errs;
|
||||
};
|
||||
|
@ -981,7 +981,7 @@ impl Context {
|
|||
)?;
|
||||
let op = hir::Expr::Accessor(hir::Accessor::private(symbol, vi));
|
||||
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 {
|
||||
return errs;
|
||||
};
|
||||
|
@ -1575,41 +1575,62 @@ impl Context {
|
|||
kw_args: &[hir::KwArg],
|
||||
input: &Input,
|
||||
namespace: &Str,
|
||||
) -> TyCheckResult<VarInfo> {
|
||||
) -> Result<VarInfo, (Option<VarInfo>, TyCheckErrors)> {
|
||||
if let hir::Expr::Accessor(hir::Accessor::Ident(local)) = obj {
|
||||
if local.vis().is_private() {
|
||||
match &local.inspect()[..] {
|
||||
"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!" => {
|
||||
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!(
|
||||
"Found:\ncallee: {obj}{}\nfound: {found}",
|
||||
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!(
|
||||
"Instantiated:\ninstance: {instance}\npos_args: ({})\nkw_args: ({})",
|
||||
fmt_slice(pos_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::__Call__(__call__) => __call__,
|
||||
SubstituteResult::Coerced(coerced) => coerced,
|
||||
};
|
||||
debug_assert!(!instance.is_quantified_subr());
|
||||
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");
|
||||
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");
|
||||
let res = VarInfo { t: res, ..found };
|
||||
Ok(res)
|
||||
|
|
|
@ -153,7 +153,7 @@ impl ASTLowerer {
|
|||
}
|
||||
|
||||
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![];
|
||||
for arg in pos_args_.into_iter() {
|
||||
let arg = self.fake_lower_expr(arg.expr)?;
|
||||
|
@ -171,7 +171,7 @@ impl ASTLowerer {
|
|||
let expr = self.fake_lower_expr(kw_arg.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)
|
||||
}
|
||||
|
||||
|
@ -206,12 +206,12 @@ impl ASTLowerer {
|
|||
}
|
||||
ast::Array::Normal(arr) => {
|
||||
let mut elems = Vec::new();
|
||||
let (elems_, ..) = arr.elems.deconstruct();
|
||||
let (elems_, .., commas) = arr.elems.deconstruct();
|
||||
for elem in elems_.into_iter() {
|
||||
let elem = self.fake_lower_expr(elem.expr)?;
|
||||
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(
|
||||
arr.l_sqbr,
|
||||
arr.r_sqbr,
|
||||
|
@ -232,12 +232,12 @@ impl ASTLowerer {
|
|||
match tup {
|
||||
ast::Tuple::Normal(tup) => {
|
||||
let mut elems = Vec::new();
|
||||
let (elems_, _, _, paren) = tup.elems.deconstruct();
|
||||
let (elems_, _, _, paren, commas) = tup.elems.deconstruct();
|
||||
for elem in elems_.into_iter() {
|
||||
let elem = self.fake_lower_expr(elem.expr)?;
|
||||
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)))
|
||||
}
|
||||
}
|
||||
|
@ -290,7 +290,7 @@ impl ASTLowerer {
|
|||
let elem = self.fake_lower_expr(elem.expr)?;
|
||||
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(
|
||||
set.l_brace,
|
||||
set.r_brace,
|
||||
|
@ -334,7 +334,7 @@ impl ASTLowerer {
|
|||
}
|
||||
|
||||
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![];
|
||||
for non_default_ in non_defaults_.into_iter() {
|
||||
let non_default =
|
||||
|
@ -355,7 +355,13 @@ impl ASTLowerer {
|
|||
let default = hir::DefaultParamSignature::new(sig, default_val);
|
||||
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> {
|
||||
|
|
|
@ -169,6 +169,7 @@ pub struct Args {
|
|||
pub var_args: Option<Box<PosArg>>,
|
||||
pub kw_args: Vec<KwArg>,
|
||||
pub paren: Option<(Token, Token)>,
|
||||
pub commas: Vec<Token>,
|
||||
}
|
||||
|
||||
impl NestedDisplay for Args {
|
||||
|
@ -244,26 +245,35 @@ impl Args {
|
|||
var_args: Option<PosArg>,
|
||||
kw_args: Vec<KwArg>,
|
||||
paren: Option<(Token, Token)>,
|
||||
commas: Vec<Token>,
|
||||
) -> Self {
|
||||
Self {
|
||||
pos_args,
|
||||
var_args: var_args.map(Box::new),
|
||||
kw_args,
|
||||
paren,
|
||||
commas,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn values(exprs: Vec<Expr>, paren: Option<(Token, Token)>) -> Self {
|
||||
Self::new(
|
||||
exprs.into_iter().map(PosArg::new).collect(),
|
||||
None,
|
||||
vec![],
|
||||
paren,
|
||||
)
|
||||
pub fn values(exprs: Vec<Expr>, paren: Option<(Token, Token)>, commas: Vec<Token>) -> Self {
|
||||
Self::pos_only(exprs.into_iter().map(PosArg::new).collect(), paren, commas)
|
||||
}
|
||||
|
||||
pub fn single(pos_arg: PosArg) -> Self {
|
||||
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 {
|
||||
Self::new(vec![], None, vec![], None)
|
||||
Self::new(vec![], None, vec![], None, vec![])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -1673,6 +1683,7 @@ pub struct Params {
|
|||
pub var_params: Option<Box<NonDefaultParamSignature>>,
|
||||
pub defaults: Vec<DefaultParamSignature>,
|
||||
pub parens: Option<(Token, Token)>,
|
||||
pub commas: Vec<Token>,
|
||||
}
|
||||
|
||||
impl fmt::Display for Params {
|
||||
|
@ -1742,18 +1753,28 @@ type RefRawParams<'a> = (
|
|||
impl Params {
|
||||
pub const fn new(
|
||||
non_defaults: Vec<NonDefaultParamSignature>,
|
||||
var_args: Option<Box<NonDefaultParamSignature>>,
|
||||
var_params: Option<Box<NonDefaultParamSignature>>,
|
||||
defaults: Vec<DefaultParamSignature>,
|
||||
parens: Option<(Token, Token)>,
|
||||
commas: Vec<Token>,
|
||||
) -> Self {
|
||||
Self {
|
||||
non_defaults,
|
||||
var_params: var_args,
|
||||
var_params,
|
||||
defaults,
|
||||
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 {
|
||||
(
|
||||
&self.non_defaults,
|
||||
|
|
|
@ -326,7 +326,7 @@ impl<'a> Linker<'a> {
|
|||
let code = Expr::Code(Block::new(Vec::from(hir.module)));
|
||||
let module_type =
|
||||
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 tmp = Identifier::private_with_line(Str::from(fresh_varname()), line);
|
||||
let mod_def = Expr::Def(Def::new(
|
||||
|
@ -338,19 +338,14 @@ impl<'a> Linker<'a> {
|
|||
let m_dict = module.clone().attr_expr(__dict__);
|
||||
let locals = Expr::Accessor(Accessor::public_with_line(Str::ever("locals"), line));
|
||||
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(
|
||||
m_dict.clone(),
|
||||
Some(Identifier::public("update")),
|
||||
args,
|
||||
));
|
||||
let exec = Expr::Accessor(Accessor::public_with_line(Str::ever("exec"), line));
|
||||
let args = Args::new(
|
||||
vec![PosArg::new(code), PosArg::new(m_dict)],
|
||||
None,
|
||||
vec![],
|
||||
None,
|
||||
);
|
||||
let args = Args::pos_only(vec![PosArg::new(code), PosArg::new(m_dict)], None, vec![]);
|
||||
let exec_code = exec.call_expr(args);
|
||||
let compound = Block::new(vec![mod_def, mod_update, exec_code, module]);
|
||||
*expr = Expr::Compound(compound);
|
||||
|
|
|
@ -248,9 +248,9 @@ impl ASTLowerer {
|
|||
log!(info "entered {}({array})", fn_name!());
|
||||
let allow_cast = true;
|
||||
let mut new_array = vec![];
|
||||
let (elems, _) = array.elems.into_iters();
|
||||
let (elems, .., commas) = array.elems.deconstruct();
|
||||
let mut union = Type::Never;
|
||||
for elem in elems {
|
||||
for elem in elems.into_iter() {
|
||||
let elem = self.lower_expr(elem.expr)?;
|
||||
let union_ = self.module.context.union(&union, elem.ref_t());
|
||||
if let Some((l, r)) = union_.union_types() {
|
||||
|
@ -291,7 +291,7 @@ impl ASTLowerer {
|
|||
array.l_sqbr,
|
||||
array.r_sqbr,
|
||||
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> {
|
||||
log!(info "entered {}({tuple})", fn_name!());
|
||||
let mut new_tuple = vec![];
|
||||
let (elems, .., paren) = tuple.elems.deconstruct();
|
||||
let (elems, .., paren, commas) = tuple.elems.deconstruct();
|
||||
for elem in elems {
|
||||
let elem = self.lower_expr(elem.expr)?;
|
||||
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> {
|
||||
|
@ -399,7 +401,7 @@ impl ASTLowerer {
|
|||
|
||||
fn lower_normal_set(&mut self, set: ast::NormalSet) -> LowerResult<hir::NormalSet> {
|
||||
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 new_set = vec![];
|
||||
for elem in elems {
|
||||
|
@ -458,7 +460,7 @@ impl ASTLowerer {
|
|||
}
|
||||
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
|
||||
if let Err(errs) = self
|
||||
.module
|
||||
|
@ -720,12 +722,13 @@ impl ASTLowerer {
|
|||
}
|
||||
|
||||
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(
|
||||
Vec::with_capacity(pos_args.len()),
|
||||
None,
|
||||
Vec::with_capacity(kw_args.len()),
|
||||
paren,
|
||||
commas,
|
||||
);
|
||||
for arg in pos_args.into_iter() {
|
||||
match self.lower_expr(arg.expr) {
|
||||
|
@ -761,6 +764,8 @@ impl ASTLowerer {
|
|||
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> {
|
||||
log!(info "entered {}({}{}(...))", fn_name!(), call.obj, fmt_option!(call.attr_name));
|
||||
if let Some(name) = call.obj.get_name() {
|
||||
|
@ -810,10 +815,10 @@ impl ASTLowerer {
|
|||
&self.module.context.name,
|
||||
) {
|
||||
Ok(vi) => vi,
|
||||
Err(es) => {
|
||||
Err((vi, es)) => {
|
||||
self.module.context.higher_order_caller.pop();
|
||||
errs.extend(es);
|
||||
return Err(errs);
|
||||
vi.unwrap_or(VarInfo::ILLEGAL.clone())
|
||||
}
|
||||
};
|
||||
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)
|
||||
} else {
|
||||
Err(errs)
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_pack(&mut self, pack: ast::DataPack) -> LowerResult<hir::Call> {
|
||||
|
@ -903,15 +905,21 @@ impl ASTLowerer {
|
|||
pack.connector.col_begin,
|
||||
)),
|
||||
);
|
||||
let vi = self.module.context.get_call_t(
|
||||
let vi = match self.module.context.get_call_t(
|
||||
&class,
|
||||
&Some(attr_name.clone()),
|
||||
&args,
|
||||
&[],
|
||||
&self.cfg.input,
|
||||
&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);
|
||||
Ok(hir::Call::new(class, Some(attr_name), args))
|
||||
}
|
||||
|
@ -983,6 +991,7 @@ impl ASTLowerer {
|
|||
hir_var_params,
|
||||
hir_defaults,
|
||||
params.parens,
|
||||
params.commas,
|
||||
);
|
||||
Ok(hir_params)
|
||||
}
|
||||
|
|
|
@ -718,6 +718,7 @@ pub enum Type {
|
|||
param_ts: Vec<Type>,
|
||||
return_t: Box<Type>,
|
||||
},
|
||||
// Overloaded(Vec<Type>),
|
||||
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}
|
||||
// 区間型と列挙型は篩型に変換される
|
||||
|
|
|
@ -161,7 +161,9 @@ pub struct Args {
|
|||
pos_args: Vec<PosArg>,
|
||||
pub(crate) var_args: Option<Box<PosArg>>,
|
||||
kw_args: Vec<KwArg>,
|
||||
// these are for ELS
|
||||
pub paren: Option<(Token, Token)>,
|
||||
pub commas: Vec<Token>,
|
||||
}
|
||||
|
||||
impl NestedDisplay for Args {
|
||||
|
@ -199,21 +201,31 @@ impl Args {
|
|||
var_args: Option<PosArg>,
|
||||
kw_args: Vec<KwArg>,
|
||||
paren: Option<(Token, Token)>,
|
||||
commas: Vec<Token>,
|
||||
) -> Self {
|
||||
Self {
|
||||
pos_args,
|
||||
var_args: var_args.map(Box::new),
|
||||
kw_args,
|
||||
paren,
|
||||
commas,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pos_only(pos_args: Vec<PosArg>, paren: Option<(Token, Token)>) -> Self {
|
||||
Self::new(pos_args, None, vec![], paren)
|
||||
pub fn pos_only(
|
||||
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 {
|
||||
Self::new(vec![], None, vec![], None)
|
||||
Self::new(vec![], None, vec![], None, vec![])
|
||||
}
|
||||
|
||||
// for replacing to hir::Args
|
||||
|
@ -225,12 +237,14 @@ impl Args {
|
|||
Option<PosArg>,
|
||||
Vec<KwArg>,
|
||||
Option<(Token, Token)>,
|
||||
Vec<Token>,
|
||||
) {
|
||||
(
|
||||
self.pos_args,
|
||||
self.var_args.map(|x| *x),
|
||||
self.kw_args,
|
||||
self.paren,
|
||||
self.commas,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -294,6 +308,14 @@ impl Args {
|
|||
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> {
|
||||
if !self.pos_args.is_empty() {
|
||||
self.pos_args.get(0).map(|a| &a.expr)
|
||||
|
@ -1894,6 +1916,7 @@ pub struct ConstArgs {
|
|||
var_args: Option<Box<ConstPosArg>>,
|
||||
kw_args: Vec<ConstKwArg>,
|
||||
paren: Option<(Token, Token)>,
|
||||
commas: Vec<Token>,
|
||||
}
|
||||
|
||||
impl NestedDisplay for ConstArgs {
|
||||
|
@ -1928,17 +1951,23 @@ impl ConstArgs {
|
|||
var_args: Option<ConstPosArg>,
|
||||
kw_args: Vec<ConstKwArg>,
|
||||
paren: Option<(Token, Token)>,
|
||||
commas: Vec<Token>,
|
||||
) -> Self {
|
||||
Self {
|
||||
pos_args,
|
||||
var_args: var_args.map(Box::new),
|
||||
kw_args,
|
||||
paren,
|
||||
commas,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pos_only(pos_args: Vec<ConstPosArg>, paren: Option<(Token, Token)>) -> Self {
|
||||
Self::new(pos_args, None, vec![], paren)
|
||||
pub fn pos_only(
|
||||
pos_args: Vec<ConstPosArg>,
|
||||
paren: Option<(Token, Token)>,
|
||||
commas: Vec<Token>,
|
||||
) -> Self {
|
||||
Self::new(pos_args, None, vec![], paren, commas)
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
|
@ -1949,17 +1978,19 @@ impl ConstArgs {
|
|||
Option<ConstPosArg>,
|
||||
Vec<ConstKwArg>,
|
||||
Option<(Token, Token)>,
|
||||
Vec<Token>,
|
||||
) {
|
||||
(
|
||||
self.pos_args,
|
||||
self.var_args.map(|x| *x),
|
||||
self.kw_args,
|
||||
self.paren,
|
||||
self.commas,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn empty() -> Self {
|
||||
Self::new(vec![], None, vec![], None)
|
||||
Self::new(vec![], None, vec![], None, vec![])
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
|
@ -1992,7 +2023,7 @@ impl ConstArgs {
|
|||
}
|
||||
|
||||
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(
|
||||
pos_args
|
||||
.into_iter()
|
||||
|
@ -2005,6 +2036,7 @@ impl ConstArgs {
|
|||
.map(|arg| KwArg::new(arg.keyword, None, arg.expr.downcast()))
|
||||
.collect(),
|
||||
paren,
|
||||
commas,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -2417,6 +2449,7 @@ impl TypeSpec {
|
|||
None,
|
||||
vec![],
|
||||
None,
|
||||
vec![],
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -3311,6 +3344,7 @@ pub struct Params {
|
|||
pub var_params: Option<Box<NonDefaultParamSignature>>,
|
||||
pub defaults: Vec<DefaultParamSignature>,
|
||||
pub parens: Option<(Token, Token)>,
|
||||
pub commas: Vec<Token>,
|
||||
}
|
||||
|
||||
impl fmt::Display for Params {
|
||||
|
@ -3354,6 +3388,7 @@ type RawParams = (
|
|||
Option<Box<NonDefaultParamSignature>>,
|
||||
Vec<DefaultParamSignature>,
|
||||
Option<(Token, Token)>,
|
||||
Vec<Token>,
|
||||
);
|
||||
|
||||
impl Params {
|
||||
|
@ -3362,21 +3397,28 @@ impl Params {
|
|||
var_params: Option<NonDefaultParamSignature>,
|
||||
defaults: Vec<DefaultParamSignature>,
|
||||
parens: Option<(Token, Token)>,
|
||||
commas: Vec<Token>,
|
||||
) -> Self {
|
||||
Self {
|
||||
non_defaults,
|
||||
var_params: var_params.map(Box::new),
|
||||
defaults,
|
||||
parens,
|
||||
commas,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn single(non_default: NonDefaultParamSignature) -> Self {
|
||||
Self::new(vec![non_default], None, vec![], None, vec![])
|
||||
}
|
||||
|
||||
pub fn deconstruct(self) -> RawParams {
|
||||
(
|
||||
self.non_defaults,
|
||||
self.var_params,
|
||||
self.defaults,
|
||||
self.parens,
|
||||
self.commas,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -3522,7 +3564,7 @@ impl LambdaSignature {
|
|||
pub fn do_sig(do_symbol: &Token) -> Self {
|
||||
let parens = Some((do_symbol.clone(), do_symbol.clone()));
|
||||
Self::new(
|
||||
Params::new(vec![], None, vec![], parens),
|
||||
Params::new(vec![], None, vec![], parens, vec![]),
|
||||
None,
|
||||
TypeBoundSpecs::empty(),
|
||||
)
|
||||
|
|
|
@ -211,7 +211,7 @@ impl Parser {
|
|||
let mut vars = Vars::empty();
|
||||
match tuple {
|
||||
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 {
|
||||
let sig = self
|
||||
.convert_rhs_to_sig(arg.expr)
|
||||
|
@ -321,7 +321,7 @@ impl Parser {
|
|||
) -> ParseResult<TypeBoundSpecs> {
|
||||
debug_call_info!(self);
|
||||
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() {
|
||||
let bound = self
|
||||
.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> {
|
||||
debug_call_info!(self);
|
||||
let (pos_args, var_args, kw_args, parens) = args.deconstruct();
|
||||
let mut params = Params::new(vec![], None, vec![], parens);
|
||||
let (pos_args, var_args, kw_args, parens, commas) = args.deconstruct();
|
||||
let mut params = Params::new(vec![], None, vec![], parens, commas);
|
||||
for (i, arg) in pos_args.into_iter().enumerate() {
|
||||
let nd_param = self
|
||||
.convert_pos_arg_to_non_default_param(arg, i == 0)
|
||||
|
@ -519,7 +519,7 @@ impl Parser {
|
|||
for arg in arr.elems.into_iters().0 {
|
||||
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);
|
||||
Ok(ParamArrayPattern::new(arr.l_sqbr, params, arr.r_sqbr))
|
||||
}
|
||||
|
@ -598,7 +598,7 @@ impl Parser {
|
|||
match tuple {
|
||||
Tuple::Normal(tup) => {
|
||||
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() {
|
||||
params.push(self.convert_pos_arg_to_non_default_param(arg, false)?);
|
||||
}
|
||||
|
@ -608,7 +608,7 @@ impl Parser {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
let params = Params::new(params, var_params, vec![], parens);
|
||||
let params = Params::new(params, var_params, vec![], parens, commas);
|
||||
debug_exit_info!(self);
|
||||
Ok(ParamTuplePattern::new(params))
|
||||
}
|
||||
|
@ -634,14 +634,14 @@ impl Parser {
|
|||
match rhs {
|
||||
Expr::Literal(lit) => {
|
||||
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()))
|
||||
}
|
||||
Expr::Accessor(accessor) => {
|
||||
let param = self
|
||||
.convert_accessor_to_param_sig(accessor)
|
||||
.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);
|
||||
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
|
||||
}
|
||||
|
@ -657,7 +657,7 @@ impl Parser {
|
|||
.convert_array_to_param_array_pat(array)
|
||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
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);
|
||||
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
|
||||
}
|
||||
|
@ -666,7 +666,7 @@ impl Parser {
|
|||
.convert_record_to_param_record_pat(record)
|
||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
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);
|
||||
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
|
||||
}
|
||||
|
@ -683,7 +683,7 @@ impl Parser {
|
|||
let param = self
|
||||
.convert_rhs_to_param(*exprs.next().unwrap(), false)
|
||||
.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);
|
||||
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
|
||||
}
|
||||
|
@ -731,8 +731,8 @@ impl Parser {
|
|||
debug_call_info!(self);
|
||||
match tuple {
|
||||
Tuple::Normal(tup) => {
|
||||
let (pos_args, var_args, kw_args, paren) = tup.elems.deconstruct();
|
||||
let mut params = Params::new(vec![], None, vec![], paren);
|
||||
let (pos_args, var_args, kw_args, paren, commas) = tup.elems.deconstruct();
|
||||
let mut params = Params::new(vec![], None, vec![], paren, commas);
|
||||
for (i, arg) in pos_args.into_iter().enumerate() {
|
||||
let param = self
|
||||
.convert_pos_arg_to_non_default_param(arg, i == 0)
|
||||
|
@ -767,7 +767,7 @@ impl Parser {
|
|||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
debug_exit_info!(self);
|
||||
Ok(LambdaSignature::new(
|
||||
Params::new(vec![sig], None, vec![], None),
|
||||
Params::single(sig),
|
||||
None,
|
||||
TypeBoundSpecs::empty(),
|
||||
))
|
||||
|
|
|
@ -62,7 +62,7 @@ impl Desugarer {
|
|||
}
|
||||
|
||||
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
|
||||
.into_iter()
|
||||
.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
|
||||
})
|
||||
.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 {
|
||||
|
@ -145,12 +145,12 @@ impl Desugarer {
|
|||
}
|
||||
Expr::Array(array) => match array {
|
||||
Array::Normal(arr) => {
|
||||
let (elems, _, _, _) = arr.elems.deconstruct();
|
||||
let (elems, _, _, _, commas) = arr.elems.deconstruct();
|
||||
let elems = elems
|
||||
.into_iter()
|
||||
.map(|elem| PosArg::new(desugar(elem.expr)))
|
||||
.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);
|
||||
Expr::Array(Array::Normal(arr))
|
||||
}
|
||||
|
@ -175,24 +175,24 @@ impl Desugarer {
|
|||
},
|
||||
Expr::Tuple(tuple) => match tuple {
|
||||
Tuple::Normal(tup) => {
|
||||
let (elems, _, _, paren) = tup.elems.deconstruct();
|
||||
let (elems, _, _, paren, commas) = tup.elems.deconstruct();
|
||||
let elems = elems
|
||||
.into_iter()
|
||||
.map(|elem| PosArg::new(desugar(elem.expr)))
|
||||
.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);
|
||||
Expr::Tuple(Tuple::Normal(tup))
|
||||
}
|
||||
},
|
||||
Expr::Set(set) => match set {
|
||||
astSet::Normal(set) => {
|
||||
let (elems, _, _, _) = set.elems.deconstruct();
|
||||
let (elems, _, _, _, commas) = set.elems.deconstruct();
|
||||
let elems = elems
|
||||
.into_iter()
|
||||
.map(|elem| PosArg::new(desugar(elem.expr)))
|
||||
.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);
|
||||
Expr::Set(astSet::Normal(set))
|
||||
}
|
||||
|
@ -359,7 +359,7 @@ impl Desugarer {
|
|||
));
|
||||
let param =
|
||||
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(
|
||||
set! {},
|
||||
name,
|
||||
|
@ -425,6 +425,7 @@ impl Desugarer {
|
|||
PosArg::new(Expr::Lambda(second_branch)),
|
||||
],
|
||||
None,
|
||||
vec![],
|
||||
);
|
||||
let call = match_symbol.call(args);
|
||||
(call, return_t_spec)
|
||||
|
@ -781,7 +782,7 @@ impl Desugarer {
|
|||
kind: TokenKind::RBrace,
|
||||
..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))
|
||||
}
|
||||
|
||||
|
@ -841,7 +842,7 @@ impl Desugarer {
|
|||
..lit.token
|
||||
};
|
||||
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 = TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr);
|
||||
param.t_spec = Some(t_spec);
|
||||
|
@ -879,6 +880,7 @@ impl Desugarer {
|
|||
let t_spec_as_expr = Expr::from(NormalTuple::new(Args::pos_only(
|
||||
ty_exprs,
|
||||
tup.elems.parens.clone(),
|
||||
tup.elems.commas.clone(),
|
||||
)));
|
||||
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(
|
||||
ty_exprs,
|
||||
tup.elems.parens.clone(),
|
||||
tup.elems.commas.clone(),
|
||||
)));
|
||||
sig.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr));
|
||||
}
|
||||
|
@ -1218,10 +1221,7 @@ impl Desugarer {
|
|||
match acc {
|
||||
// x[y] => x.__getitem__(y)
|
||||
Accessor::Subscr(subscr) => {
|
||||
let args = Args::pos_only(
|
||||
vec![PosArg::new(Self::rec_desugar_acc(*subscr.index))],
|
||||
None,
|
||||
);
|
||||
let args = Args::single(PosArg::new(Self::rec_desugar_acc(*subscr.index)));
|
||||
let line = subscr.obj.ln_begin().unwrap();
|
||||
let call = Call::new(
|
||||
Self::rec_desugar_acc(*subscr.obj),
|
||||
|
@ -1236,7 +1236,7 @@ impl Desugarer {
|
|||
}
|
||||
// x.0 => x.__Tuple_getitem__(0)
|
||||
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 call = Call::new(
|
||||
Self::rec_desugar_acc(*tattr.obj),
|
||||
|
|
|
@ -560,7 +560,7 @@ impl Parser {
|
|||
let first = self
|
||||
.try_reduce_elem()
|
||||
.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() {
|
||||
Some(Semi) => {
|
||||
self.lpop();
|
||||
|
@ -691,11 +691,15 @@ impl Parser {
|
|||
Some(RParen) => {
|
||||
rp = Some(self.lpop());
|
||||
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) => {
|
||||
debug_exit_info!(self);
|
||||
return Ok(Args::pos_only(vec![], None));
|
||||
return Ok(Args::empty());
|
||||
}
|
||||
Some(Newline) if style.needs_parens() => {
|
||||
self.skip();
|
||||
|
@ -714,17 +718,17 @@ impl Parser {
|
|||
expr: Expr::UnaryOp(unary),
|
||||
}) if unary.op.is(PreStar) => {
|
||||
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 {
|
||||
expr: Expr::TypeAscription(TypeAscription { expr, t_spec }),
|
||||
}) if matches!(expr.as_ref(), Expr::UnaryOp(unary) if unary.op.is(PreStar)) => {
|
||||
let Expr::UnaryOp(unary) = *expr else { unreachable!() };
|
||||
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::Kw(arg) => Args::new(vec![], None, vec![arg], None),
|
||||
PosOrKwArg::Pos(arg) => Args::single(arg),
|
||||
PosOrKwArg::Kw(arg) => Args::new(vec![], None, vec![arg], None, vec![]),
|
||||
};
|
||||
loop {
|
||||
match self.peek_kind() {
|
||||
|
@ -750,7 +754,7 @@ impl Parser {
|
|||
self.skip();
|
||||
}
|
||||
Some(Comma) => {
|
||||
self.skip();
|
||||
args.push_comma(self.lpop());
|
||||
if style.is_colon() || self.cur_is(Comma) {
|
||||
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||
self.errs.push(err);
|
||||
|
@ -767,8 +771,7 @@ impl Parser {
|
|||
}
|
||||
if style.needs_parens() && self.cur_is(RParen) {
|
||||
let rp = self.lpop();
|
||||
let (pos_args, var_args, kw_args, _) = args.deconstruct();
|
||||
args = Args::new(pos_args, var_args, kw_args, Some((lp.unwrap(), rp)));
|
||||
args.set_parens((lp.unwrap(), rp));
|
||||
break;
|
||||
}
|
||||
if !args.kw_is_empty() {
|
||||
|
@ -807,12 +810,11 @@ impl Parser {
|
|||
Some(RParen) => {
|
||||
if let Some(lp) = lp {
|
||||
let rp = self.lpop();
|
||||
let (pos_args, var_args, kw_args, _) = args.deconstruct();
|
||||
args = Args::new(pos_args, var_args, kw_args, Some((lp, rp)));
|
||||
args.set_parens((lp, rp));
|
||||
} else {
|
||||
// e.g. f(g 1)
|
||||
let (pos_args, var_args, kw_args, _) = args.deconstruct();
|
||||
args = Args::new(pos_args, var_args, kw_args, None);
|
||||
let (pos_args, var_args, kw_args, _, commas) = args.deconstruct();
|
||||
args = Args::new(pos_args, var_args, kw_args, None, commas);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -830,8 +832,7 @@ impl Parser {
|
|||
debug_exit_info!(self);
|
||||
return Err(());
|
||||
}
|
||||
let (pos_args, var_args, kw_args, _) = args.deconstruct();
|
||||
args = Args::new(pos_args, var_args, kw_args, Some((lp.unwrap(), rp)));
|
||||
args.set_parens((lp.unwrap(), rp));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1690,9 +1691,7 @@ impl Parser {
|
|||
Signature::Var(var) => {
|
||||
let mut last = def.body.block.pop().unwrap();
|
||||
for deco in decos.into_iter() {
|
||||
last = deco
|
||||
.into_expr()
|
||||
.call_expr(Args::pos_only(vec![PosArg::new(last)], None));
|
||||
last = deco.into_expr().call_expr(Args::single(PosArg::new(last)));
|
||||
}
|
||||
def.body.block.push(last);
|
||||
let expr = Expr::Def(Def::new(Signature::Var(var), def.body));
|
||||
|
@ -1728,7 +1727,7 @@ impl Parser {
|
|||
};
|
||||
if self.cur_is(RParen) {
|
||||
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));
|
||||
debug_exit_info!(self);
|
||||
return Ok(Expr::Tuple(unit));
|
||||
|
@ -2297,7 +2296,7 @@ impl Parser {
|
|||
len,
|
||||
)));
|
||||
}
|
||||
let mut args = Args::pos_only(vec![PosArg::new(first_elem)], None);
|
||||
let mut args = Args::single(PosArg::new(first_elem));
|
||||
loop {
|
||||
match self.peek_kind() {
|
||||
Some(Comma) => {
|
||||
|
@ -2370,7 +2369,7 @@ impl Parser {
|
|||
expr: Expr::UnaryOp(unary),
|
||||
}) if unary.op.is(PreStar) => {
|
||||
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 {
|
||||
expr: Expr::TypeAscription(TypeAscription { expr, t_spec }),
|
||||
|
@ -2378,10 +2377,10 @@ impl Parser {
|
|||
let Expr::UnaryOp(unary) = *expr else { unreachable!() };
|
||||
let expr = unary.deconstruct().1;
|
||||
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::Kw(kw) => Args::new(vec![], None, vec![kw], None),
|
||||
PosOrKwArg::Pos(pos) => Args::single(pos),
|
||||
PosOrKwArg::Kw(kw) => Args::new(vec![], None, vec![kw], None, vec![]),
|
||||
};
|
||||
#[allow(clippy::while_let_loop)]
|
||||
loop {
|
||||
|
@ -2502,11 +2501,7 @@ impl Parser {
|
|||
mid_expr.ln_begin().unwrap(),
|
||||
mid_expr.col_begin().unwrap(),
|
||||
);
|
||||
let call = Call::new(
|
||||
str_func,
|
||||
None,
|
||||
Args::pos_only(vec![PosArg::new(mid_expr)], None),
|
||||
);
|
||||
let call = Call::new(str_func, None, Args::single(PosArg::new(mid_expr)));
|
||||
let op = Token::new(
|
||||
Plus,
|
||||
"+",
|
||||
|
|
|
@ -16,13 +16,13 @@ impl Parser {
|
|||
}
|
||||
Expr::Array(array) => match array {
|
||||
Array::Normal(arr) => {
|
||||
let (elems, ..) = arr.elems.deconstruct();
|
||||
let (elems, .., commas) = arr.elems.deconstruct();
|
||||
let mut const_elems = vec![];
|
||||
for elem in elems.into_iter() {
|
||||
let const_expr = Self::validate_const_expr(elem.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);
|
||||
Ok(ConstExpr::Array(const_arr))
|
||||
}
|
||||
|
@ -34,13 +34,13 @@ impl Parser {
|
|||
},
|
||||
Expr::Set(set) => match set {
|
||||
Set::Normal(set) => {
|
||||
let (elems, ..) = set.elems.deconstruct();
|
||||
let (elems, .., commas) = set.elems.deconstruct();
|
||||
let mut const_elems = vec![];
|
||||
for elem in elems.into_iter() {
|
||||
let const_expr = Self::validate_const_expr(elem.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);
|
||||
Ok(ConstExpr::Set(const_set))
|
||||
}
|
||||
|
@ -69,13 +69,13 @@ impl Parser {
|
|||
},
|
||||
Expr::Tuple(tuple) => match tuple {
|
||||
Tuple::Normal(tup) => {
|
||||
let (elems, _, _, paren) = tup.elems.deconstruct();
|
||||
let (elems, _, _, paren, commas) = tup.elems.deconstruct();
|
||||
let mut const_elems = vec![];
|
||||
for elem in elems.into_iter() {
|
||||
let const_expr = Self::validate_const_expr(elem.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);
|
||||
Ok(ConstExpr::Tuple(const_tup))
|
||||
}
|
||||
|
@ -100,13 +100,13 @@ impl Parser {
|
|||
"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![];
|
||||
for elem in pos_args.into_iter() {
|
||||
let const_expr = Self::validate_const_expr(elem.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)))
|
||||
}
|
||||
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> {
|
||||
match *call.obj {
|
||||
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![];
|
||||
for arg in _pos_args.into_iter() {
|
||||
let const_expr = Self::validate_const_expr(arg.expr)?;
|
||||
|
@ -213,7 +213,7 @@ impl Parser {
|
|||
}
|
||||
Ok(PreDeclTypeSpec::Simple(SimpleTypeSpec::new(
|
||||
ident,
|
||||
ConstArgs::new(pos_args, var_args, kw_args, paren),
|
||||
ConstArgs::new(pos_args, var_args, kw_args, paren, commas),
|
||||
)))
|
||||
}
|
||||
_ => todo!(),
|
||||
|
@ -309,12 +309,12 @@ impl Parser {
|
|||
match set {
|
||||
Set::Normal(set) => {
|
||||
let mut elem_ts = vec![];
|
||||
let (elems, .., paren) = set.elems.deconstruct();
|
||||
let (elems, .., paren, commas) = set.elems.deconstruct();
|
||||
for elem in elems.into_iter() {
|
||||
let const_expr = Self::validate_const_expr(elem.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) => {
|
||||
let t_spec = Self::expr_to_type_spec(set.elem.expr)?;
|
||||
|
@ -375,7 +375,7 @@ impl Parser {
|
|||
match tuple {
|
||||
Tuple::Normal(tup) => {
|
||||
let mut tup_spec = vec![];
|
||||
let (elems, .., parens) = tup.elems.deconstruct();
|
||||
let (elems, .., parens, _commas) = tup.elems.deconstruct();
|
||||
for elem in elems.into_iter() {
|
||||
let value = Self::expr_to_type_spec(elem.expr)?;
|
||||
tup_spec.push(value);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue