From 6b18b2a61f01e053e0e4601e297e1049f94f2dc6 Mon Sep 17 00:00:00 2001 From: nezuo Date: Fri, 29 Nov 2024 16:59:50 -0800 Subject: [PATCH 1/8] Attach names to parameters --- zap/src/config.rs | 10 ++- zap/src/irgen/des.rs | 14 +++- zap/src/irgen/mod.rs | 4 +- zap/src/irgen/ser.rs | 14 +++- zap/src/output/luau/client.rs | 94 ++++++++++++---------- zap/src/output/luau/server.rs | 120 +++++++++++++++++----------- zap/src/output/tooling.rs | 22 ++--- zap/src/output/typescript/client.rs | 13 ++- zap/src/output/typescript/mod.rs | 21 +++-- zap/src/output/typescript/server.rs | 29 ++++--- zap/src/parser/convert.rs | 43 +++++++--- zap/src/parser/grammar.lalrpop | 20 ++++- zap/src/parser/syntax_tree.rs | 17 +++- 13 files changed, 265 insertions(+), 156 deletions(-) diff --git a/zap/src/config.rs b/zap/src/config.rs index b88383fa..c79b2f35 100644 --- a/zap/src/config.rs +++ b/zap/src/config.rs @@ -76,7 +76,7 @@ impl std::fmt::Display for YieldType { pub struct FnDecl<'src> { pub name: &'src str, pub call: FnCall, - pub args: Option>>, + pub args: Vec>, pub rets: Option>>, pub id: usize, } @@ -93,10 +93,16 @@ pub struct EvDecl<'src> { pub from: EvSource, pub evty: EvType, pub call: EvCall, - pub data: Option>>, + pub data: Vec>, pub id: usize, } +#[derive(Debug, Clone)] +pub struct Parameter<'src> { + pub name: Option<&'src str>, + pub ty: Ty<'src>, +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum EvSource { Server, diff --git a/zap/src/irgen/des.rs b/zap/src/irgen/des.rs index 860ccb74..bb2ff8a4 100644 --- a/zap/src/irgen/des.rs +++ b/zap/src/irgen/des.rs @@ -14,8 +14,11 @@ impl Gen for Des { self.buf.push(stmt); } - fn gen(mut self, var: Var, types: &[Ty]) -> Vec { - for (i, ty) in types.iter().enumerate() { + fn gen<'a, I>(mut self, var: Var, types: I) -> Vec + where + I: Iterator>, + { + for (i, ty) in types.enumerate() { let var = if i > 0 { Var::Name(match &var { Var::Name(name) => format!("{name}{}", i + 1), @@ -431,11 +434,14 @@ impl Des { } } -pub fn gen(types: &[Ty], var: &str, checks: bool) -> Vec { +pub fn gen<'a, I>(types: I, var: &str, checks: bool) -> Vec +where + I: IntoIterator>, +{ Des { checks, buf: vec![], var_occurrences: HashMap::new(), } - .gen(var.into(), types) + .gen(var.into(), types.into_iter()) } diff --git a/zap/src/irgen/mod.rs b/zap/src/irgen/mod.rs index 88c16014..1ab5bec8 100644 --- a/zap/src/irgen/mod.rs +++ b/zap/src/irgen/mod.rs @@ -9,7 +9,9 @@ pub mod ser; pub trait Gen { fn push_stmt(&mut self, stmt: Stmt); - fn gen(self, var: Var, types: &[Ty]) -> Vec; + fn gen<'a, I>(self, var: Var, types: I) -> Vec + where + I: Iterator>; fn push_local(&mut self, name: String, expr: Option) { self.push_stmt(Stmt::Local(name, expr)) diff --git a/zap/src/irgen/ser.rs b/zap/src/irgen/ser.rs index 5fcadaf0..93b3c7ad 100644 --- a/zap/src/irgen/ser.rs +++ b/zap/src/irgen/ser.rs @@ -14,8 +14,11 @@ impl Gen for Ser { self.buf.push(stmt); } - fn gen(mut self, var: Var, types: &[Ty]) -> Vec { - for (i, ty) in types.iter().enumerate() { + fn gen<'a, I>(mut self, var: Var, types: I) -> Vec + where + I: Iterator>, + { + for (i, ty) in types.enumerate() { let var = if i > 0 { Var::Name(match &var { Var::Name(name) => format!("{name}{}", i + 1), @@ -369,11 +372,14 @@ impl Ser { } } -pub fn gen(types: &[Ty], var: &str, checks: bool) -> Vec { +pub fn gen<'a, I>(types: I, var: &str, checks: bool) -> Vec +where + I: IntoIterator>, +{ Ser { checks, buf: vec![], var_occurrences: HashMap::new(), } - .gen(var.into(), types) + .gen(var.into(), types.into_iter()) } diff --git a/zap/src/output/luau/client.rs b/zap/src/output/luau/client.rs index 0e89e6ae..c3121f0e 100644 --- a/zap/src/output/luau/client.rs +++ b/zap/src/output/luau/client.rs @@ -1,5 +1,5 @@ use crate::{ - config::{Config, EvCall, EvDecl, EvSource, EvType, FnDecl, Ty, TyDecl, YieldType}, + config::{Config, EvCall, EvDecl, EvSource, EvType, FnDecl, Parameter, TyDecl, YieldType}, irgen::{des, ser}, }; @@ -174,9 +174,9 @@ impl<'src> ClientOutput<'src> { )); } - fn get_values(&self, data: &Option>) -> String { - if let Some(types) = data { - (1..=types.len()) + fn get_values(&self, count: usize) -> String { + if count > 0 { + (1..=count) .map(|i| { if i == 1 { "value".to_string() @@ -210,12 +210,12 @@ impl<'src> ClientOutput<'src> { self.indent(); - let values = self.get_values(&ev.data); + let values = self.get_values(ev.data.len()); self.push_line(&format!("local {values}")); - if let Some(data) = &ev.data { - self.push_stmts(&des::gen(data, "value", true)); + if !ev.data.is_empty() { + self.push_stmts(&des::gen(ev.data.iter().map(|parameter| ¶meter.ty), "value", true)); } if ev.call == EvCall::SingleSync || ev.call == EvCall::SingleAsync { @@ -247,8 +247,8 @@ impl<'src> ClientOutput<'src> { self.push_line("else"); self.indent(); - if let Some(types) = &ev.data { - if types.len() > 1 { + if !ev.data.is_empty() { + if ev.data.len() > 1 { self.push_line(&format!("table.insert(event_queue[{id}], {{ {values} }})")); } else { self.push_line(&format!("table.insert(event_queue[{id}], value)")); @@ -265,7 +265,7 @@ impl<'src> ClientOutput<'src> { self.push("warn(`[ZAP] {"); - if ev.data.is_some() { + if !ev.data.is_empty() { self.push("#") } @@ -304,7 +304,7 @@ impl<'src> ClientOutput<'src> { self.push_line("local call_id = buffer.readu8(incoming_buff, read(1))"); - let values = self.get_values(&fndecl.rets); + let values = self.get_values(fndecl.rets.as_ref().map_or(0, |x| x.len())); self.push_line(&format!("local {values}")); @@ -395,12 +395,16 @@ impl<'src> ClientOutput<'src> { self.indent(); - let values = self.get_values(&ev.data); + let values = self.get_values(ev.data.len()); self.push_line(&format!("local {values}")); - if let Some(data) = &ev.data { - self.push_stmts(&des::gen(data, "value", self.config.write_checks)); + if !ev.data.is_empty() { + self.push_stmts(&des::gen( + ev.data.iter().map(|parameter| ¶meter.ty), + "value", + self.config.write_checks, + )); } if ev.call == EvCall::SingleSync || ev.call == EvCall::SingleAsync { @@ -432,8 +436,8 @@ impl<'src> ClientOutput<'src> { self.push_line("else"); self.indent(); - if let Some(types) = &ev.data { - if types.len() > 1 { + if !ev.data.is_empty() { + if ev.data.len() > 1 { self.push_line(&format!("table.insert(event_queue[{id}], {{ {values} }})")); } else { self.push_line(&format!("table.insert(event_queue[{id}], value)")); @@ -450,7 +454,7 @@ impl<'src> ClientOutput<'src> { self.push("warn(`[ZAP] {"); - if ev.data.is_some() { + if !ev.data.is_empty() { self.push("#") } @@ -528,7 +532,7 @@ impl<'src> ClientOutput<'src> { self.push_line(&format!("events[{id}] = {{}}")); } - if evdecl.data.is_some() { + if !evdecl.data.is_empty() { self.push_line(&format!("event_queue[{id}] = {{}}")); } else { self.push_line(&format!("event_queue[{id}] = 0")); @@ -548,8 +552,8 @@ impl<'src> ClientOutput<'src> { )); } - fn push_value_parameters(&mut self, types: &[Ty]) { - for (i, ty) in types.iter().enumerate() { + fn push_value_parameters(&mut self, parameters: &[Parameter]) { + for (i, parameter) in parameters.iter().enumerate() { let value = format!( "{}{}", self.config.casing.with("Value", "value", "value"), @@ -561,7 +565,7 @@ impl<'src> ClientOutput<'src> { } self.push(&format!("{value}: ")); - self.push_ty(ty); + self.push_ty(¶meter.ty); } } @@ -572,8 +576,8 @@ impl<'src> ClientOutput<'src> { self.push_indent(); self.push(&format!("{fire} = function(")); - if let Some(types) = &ev.data { - self.push_value_parameters(types); + if !ev.data.is_empty() { + self.push_value_parameters(&ev.data); } self.push(")\n"); @@ -586,8 +590,12 @@ impl<'src> ClientOutput<'src> { self.push_write_event_id(ev.id); - if let Some(data) = &ev.data { - self.push_stmts(&ser::gen(data, value, self.config.write_checks)); + if !ev.data.is_empty() { + self.push_stmts(&ser::gen( + ev.data.iter().map(|parameter| ¶meter.ty), + value, + self.config.write_checks, + )); } if ev.evty == EvType::Unreliable { @@ -618,8 +626,8 @@ impl<'src> ClientOutput<'src> { } } - fn push_queued_value(&mut self, types: &[Ty]) { - if types.len() > 1 { + fn push_queued_value(&mut self, parameters: &[Parameter]) { + if parameters.len() > 1 { self.push("unpack(value)"); } else { self.push("value"); @@ -635,8 +643,8 @@ impl<'src> ClientOutput<'src> { self.push_indent(); self.push(&format!("{set_callback} = function({callback}: (")); - if let Some(types) = &ev.data { - self.push_value_parameters(types); + if !ev.data.is_empty() { + self.push_value_parameters(&ev.data); } self.push(") -> ()): () -> ()\n"); @@ -644,19 +652,19 @@ impl<'src> ClientOutput<'src> { self.push_line(&format!("events[{id}] = {callback}")); - if let Some(types) = &ev.data { + if !ev.data.is_empty() { self.push_line(&format!("for _, value in event_queue[{id}] do")); self.indent(); if ev.call == EvCall::SingleSync { self.push_indent(); self.push(&format!("{callback}(")); - self.push_queued_value(types); + self.push_queued_value(&ev.data); self.push_line(")\n"); } else { self.push_indent(); self.push(&format!("task.spawn({callback}, ")); - self.push_queued_value(types); + self.push_queued_value(&ev.data); self.push(")\n"); } @@ -701,8 +709,8 @@ impl<'src> ClientOutput<'src> { self.push_indent(); self.push(&format!("{on} = function({callback}: (")); - if let Some(types) = &ev.data { - self.push_value_parameters(types); + if !ev.data.is_empty() { + self.push_value_parameters(&ev.data); } self.push(") -> ())\n"); @@ -710,19 +718,19 @@ impl<'src> ClientOutput<'src> { self.push_line(&format!("table.insert(events[{id}], {callback})")); - if let Some(types) = &ev.data { + if !ev.data.is_empty() { self.push_line(&format!("for _, value in event_queue[{id}] do")); self.indent(); if ev.call == EvCall::ManySync { self.push_indent(); self.push(&format!("{callback}(")); - self.push_queued_value(types); + self.push_queued_value(&ev.data); self.push_line(")\n"); } else { self.push_indent(); self.push(&format!("task.spawn({callback}, ")); - self.push_queued_value(types); + self.push_queued_value(&ev.data); self.push(")\n"); } @@ -793,8 +801,8 @@ impl<'src> ClientOutput<'src> { self.push_indent(); self.push(&format!("{call} = function(")); - if let Some(types) = &fndecl.args { - self.push_value_parameters(types); + if !fndecl.args.is_empty() { + self.push_value_parameters(&fndecl.args); } self.push(")"); @@ -848,8 +856,12 @@ impl<'src> ClientOutput<'src> { self.push_line("alloc(1)"); self.push_line("buffer.writeu8(outgoing_buff, outgoing_apos, function_call_id)"); - if let Some(data) = &fndecl.args { - self.push_stmts(&ser::gen(data, value, self.config.write_checks)); + if !fndecl.args.is_empty() { + self.push_stmts(&ser::gen( + fndecl.args.iter().map(|parameter| ¶meter.ty), + value, + self.config.write_checks, + )); } match self.config.yield_type { diff --git a/zap/src/output/luau/server.rs b/zap/src/output/luau/server.rs index 3e0557e5..f4f567a3 100644 --- a/zap/src/output/luau/server.rs +++ b/zap/src/output/luau/server.rs @@ -1,5 +1,5 @@ use crate::{ - config::{Config, EvCall, EvDecl, EvSource, EvType, FnCall, FnDecl, Ty, TyDecl}, + config::{Config, EvCall, EvDecl, EvSource, EvType, FnCall, FnDecl, Parameter, TyDecl}, irgen::{des, ser}, }; @@ -186,9 +186,9 @@ impl<'a> ServerOutput<'a> { )); } - fn get_values(&self, data: &Option>) -> String { - if let Some(types) = data { - (1..=types.len()) + fn get_values(&self, parameters: &[Parameter]) -> String { + if !parameters.is_empty() { + (1..=parameters.len()) .map(|i| { if i == 1 { "value".to_string() @@ -226,8 +226,8 @@ impl<'a> ServerOutput<'a> { self.push_line(&format!("local {values}")); - if let Some(data) = &ev.data { - self.push_stmts(&des::gen(data, "value", true)); + if !ev.data.is_empty() { + self.push_stmts(&des::gen(ev.data.iter().map(|parameter| ¶meter.ty), "value", true)); } if ev.call == EvCall::SingleSync || ev.call == EvCall::SingleAsync { @@ -273,16 +273,20 @@ impl<'a> ServerOutput<'a> { self.push_line(&format!("local {values}")); - if let Some(data) = &fndecl.args { - self.push_stmts(&des::gen(data, "value", true)); + if !fndecl.args.is_empty() { + self.push_stmts(&des::gen( + fndecl.args.iter().map(|parameter| ¶meter.ty), + "value", + true, + )); } self.push_line(&format!("if events[{id}] then")); self.indent(); - let rets = if let Some(types) = &fndecl.args { - (1..=types.len()) + let rets = if !fndecl.args.is_empty() { + (1..=fndecl.args.len()) .map(|i| { if i > 1 { format!("rets{}", i) @@ -297,8 +301,8 @@ impl<'a> ServerOutput<'a> { }; if fndecl.call == FnCall::Async { - let args = if let Some(types) = &fndecl.args { - (1..=types.len()) + let args = if !fndecl.args.is_empty() { + (1..=fndecl.args.len()) .map(|i| format!("value_{}", i)) .collect::>() .join(", ") @@ -421,8 +425,8 @@ impl<'a> ServerOutput<'a> { self.push_line(&format!("local {}", values)); - if let Some(data) = &ev.data { - self.push_stmts(&des::gen(data, "value", true)); + if !ev.data.is_empty() { + self.push_stmts(&des::gen(ev.data.iter().map(|parameter| ¶meter.ty), "value", true)); } if ev.call == EvCall::SingleSync || ev.call == EvCall::SingleAsync { @@ -495,8 +499,8 @@ impl<'a> ServerOutput<'a> { )); } - fn push_value_parameters(&mut self, types: &[Ty]) { - for (i, ty) in types.iter().enumerate() { + fn push_value_parameters(&mut self, parameters: &[Parameter]) { + for (i, parameter) in parameters.iter().enumerate() { let value = format!( "{}{}", self.config.casing.with("Value", "value", "value"), @@ -508,12 +512,12 @@ impl<'a> ServerOutput<'a> { } self.push(&format!("{value}: ")); - self.push_ty(ty); + self.push_ty(¶meter.ty); } } fn push_return_fire(&mut self, ev: &EvDecl) { - let types = &ev.data; + let parameters = &ev.data; let fire = self.config.casing.with("Fire", "fire", "fire"); let player = self.config.casing.with("Player", "player", "player"); @@ -522,9 +526,9 @@ impl<'a> ServerOutput<'a> { self.push_indent(); self.push(&format!("{fire} = function({player}: Player")); - if let Some(types) = types { + if !parameters.is_empty() { self.push(", "); - self.push_value_parameters(types); + self.push_value_parameters(parameters); } self.push(")\n"); @@ -537,8 +541,12 @@ impl<'a> ServerOutput<'a> { self.push_write_event_id(ev.id); - if let Some(types) = types { - self.push_stmts(&ser::gen(types, value, self.config.write_checks)); + if !parameters.is_empty() { + self.push_stmts(&ser::gen( + parameters.iter().map(|parameter| ¶meter.ty), + value, + self.config.write_checks, + )); } match ev.evty { @@ -555,7 +563,7 @@ impl<'a> ServerOutput<'a> { } fn push_return_fire_all(&mut self, ev: &EvDecl) { - let types = &ev.data; + let parameters = &ev.data; let fire_all = self.config.casing.with("FireAll", "fireAll", "fire_all"); let value = self.config.casing.with("Value", "value", "value"); @@ -563,8 +571,8 @@ impl<'a> ServerOutput<'a> { self.push_indent(); self.push(&format!("{fire_all} = function(")); - if let Some(types) = types { - self.push_value_parameters(types); + if !parameters.is_empty() { + self.push_value_parameters(parameters); } self.push(")\n"); @@ -574,8 +582,12 @@ impl<'a> ServerOutput<'a> { self.push_write_event_id(ev.id); - if let Some(types) = types { - self.push_stmts(&ser::gen(types, value, self.config.write_checks)); + if !parameters.is_empty() { + self.push_stmts(&ser::gen( + parameters.iter().map(|parameter| ¶meter.ty), + value, + self.config.write_checks, + )); } match ev.evty { @@ -604,7 +616,7 @@ impl<'a> ServerOutput<'a> { } fn push_return_fire_except(&mut self, ev: &EvDecl) { - let types = &ev.data; + let parameters = &ev.data; let fire_except = self.config.casing.with("FireExcept", "fireExcept", "fire_except"); let except = self.config.casing.with("Except", "except", "except"); @@ -613,9 +625,9 @@ impl<'a> ServerOutput<'a> { self.push_indent(); self.push(&format!("{fire_except} = function({except}: Player")); - if let Some(types) = types { + if !parameters.is_empty() { self.push(", "); - self.push_value_parameters(types); + self.push_value_parameters(parameters); } self.push(")\n"); @@ -625,8 +637,12 @@ impl<'a> ServerOutput<'a> { self.push_write_event_id(ev.id); - if let Some(types) = types { - self.push_stmts(&ser::gen(types, value, self.config.write_checks)); + if !parameters.is_empty() { + self.push_stmts(&ser::gen( + parameters.iter().map(|paramater| ¶mater.ty), + value, + self.config.write_checks, + )); } match ev.evty { @@ -667,7 +683,7 @@ impl<'a> ServerOutput<'a> { } fn push_return_fire_list(&mut self, ev: &EvDecl) { - let types = &ev.data; + let parameters = &ev.data; let fire_list = self.config.casing.with("FireList", "fireList", "fire_list"); let list = self.config.casing.with("List", "list", "list"); @@ -676,9 +692,9 @@ impl<'a> ServerOutput<'a> { self.push_indent(); self.push(&format!("{fire_list} = function({list}: {{ Player }}")); - if let Some(types) = types { + if !parameters.is_empty() { self.push(", "); - self.push_value_parameters(types); + self.push_value_parameters(parameters); } self.push(")\n"); @@ -688,8 +704,12 @@ impl<'a> ServerOutput<'a> { self.push_write_event_id(ev.id); - if let Some(ty) = types { - self.push_stmts(&ser::gen(ty, value, self.config.write_checks)); + if !parameters.is_empty() { + self.push_stmts(&ser::gen( + parameters.iter().map(|parameter| ¶meter.ty), + value, + self.config.write_checks, + )); } match ev.evty { @@ -722,7 +742,7 @@ impl<'a> ServerOutput<'a> { } fn push_return_fire_set(&mut self, ev: &EvDecl) { - let types = &ev.data; + let parameters = &ev.data; let fire_set = self.config.casing.with("FireSet", "fireSet", "fire_set"); let set = self.config.casing.with("Set", "set", "set"); @@ -731,9 +751,9 @@ impl<'a> ServerOutput<'a> { self.push_indent(); self.push(&format!("{fire_set} = function({set}: {{ [Player]: true }}")); - if let Some(types) = types { + if !parameters.is_empty() { self.push(", "); - self.push_value_parameters(types); + self.push_value_parameters(parameters); } self.push(")\n"); @@ -743,8 +763,12 @@ impl<'a> ServerOutput<'a> { self.push_write_event_id(ev.id); - if let Some(ty) = types { - self.push_stmts(&ser::gen(ty, value, self.config.write_checks)); + if !parameters.is_empty() { + self.push_stmts(&ser::gen( + parameters.iter().map(|parameter| ¶meter.ty), + value, + self.config.write_checks, + )); } match ev.evty { @@ -811,9 +835,9 @@ impl<'a> ServerOutput<'a> { self.push_indent(); self.push(&format!("{set_callback} = function({callback}: ({player}: Player")); - if let Some(types) = &ev.data { + if !ev.data.is_empty() { self.push(", "); - self.push_value_parameters(types); + self.push_value_parameters(&ev.data); } self.push(") -> ()): () -> ()\n"); @@ -843,9 +867,9 @@ impl<'a> ServerOutput<'a> { self.push_indent(); self.push(&format!("{on} = function({callback}: ({player}: Player")); - if let Some(types) = &ev.data { + if !ev.data.is_empty() { self.push(", "); - self.push_value_parameters(types); + self.push_value_parameters(&ev.data); } self.push(") -> ()): () -> ()\n"); @@ -877,9 +901,9 @@ impl<'a> ServerOutput<'a> { self.push_indent(); self.push(&format!("{set_callback} = function({callback}: ({player}: Player")); - if let Some(types) = &fndecl.args { + if !fndecl.args.is_empty() { self.push(", "); - self.push_value_parameters(types); + self.push_value_parameters(&fndecl.args); } self.push(") -> ("); diff --git a/zap/src/output/tooling.rs b/zap/src/output/tooling.rs index 2a228a3d..b63688fd 100644 --- a/zap/src/output/tooling.rs +++ b/zap/src/output/tooling.rs @@ -1,5 +1,5 @@ use crate::{ - config::{Config, EvDecl, FnDecl, Ty, TyDecl}, + config::{Config, EvDecl, FnDecl, Parameter, TyDecl}, irgen::{des, Stmt}, Output, }; @@ -115,7 +115,7 @@ impl<'src> ToolingOutput<'src> { self.push_line(&format!("function types.read_{name}()")); self.indent(); self.push_line("local value;"); - self.push_stmts(&des::gen(&[ty.clone()], "value", true)); + self.push_stmts(&des::gen(std::iter::once(ty), "value", true)); self.push_line("return value"); self.dedent(); self.push_line("end"); @@ -129,9 +129,9 @@ impl<'src> ToolingOutput<'src> { } } - fn get_values(&self, data: &Option>) -> String { - if let Some(types) = data { - (1..=types.len()) + fn get_values(&self, data: &[Parameter]) -> String { + if !data.is_empty() { + (1..=data.len()) .map(|i| { if i == 1 { "value".to_string() @@ -168,8 +168,8 @@ impl<'src> ToolingOutput<'src> { self.push_line(&format!("local {values}")); - if let Some(data) = &ev.data { - self.push_stmts(&des::gen(data, "value", true)); + if !ev.data.is_empty() { + self.push_stmts(&des::gen(ev.data.iter().map(|parameter| ¶meter.ty), "value", true)); } self.push_line("table.insert(events, {"); @@ -226,8 +226,12 @@ impl<'src> ToolingOutput<'src> { self.push_line(&format!("local {values}")); - if let Some(data) = &fn_decl.args { - self.push_stmts(&des::gen(data, "value", true)); + if !fn_decl.args.is_empty() { + self.push_stmts(&des::gen( + fn_decl.args.iter().map(|parameter| ¶meter.ty), + "value", + true, + )); } self.push_line("table.insert(events, {"); diff --git a/zap/src/output/typescript/client.rs b/zap/src/output/typescript/client.rs index 2590655b..8dee730b 100644 --- a/zap/src/output/typescript/client.rs +++ b/zap/src/output/typescript/client.rs @@ -1,4 +1,3 @@ -use crate::config::Ty; use crate::config::{Config, EvCall, EvSource, TyDecl, YieldType}; use super::ConfigProvider; @@ -81,8 +80,8 @@ impl<'src> ClientOutput<'src> { self.push_indent(); self.push(&format!("{fire}: (")); - if let Some(types) = &ev.data { - self.push_parameters(types); + if !ev.data.is_empty() { + self.push_parameters(&ev.data); } self.push(") => void;\n"); @@ -114,8 +113,8 @@ impl<'src> ClientOutput<'src> { self.push_indent(); self.push(&format!("{set_callback}: ({callback}: (")); - if let Some(types) = &ev.data { - self.push_parameters(types); + if !ev.data.is_empty() { + self.push_parameters(&ev.data); } self.push(") => void) => () => void;\n"); @@ -135,8 +134,8 @@ impl<'src> ClientOutput<'src> { self.push_indent(); self.push(&format!("{call}: (")); - if let Some(types) = &fndecl.args { - self.push_parameters(types); + if !fndecl.args.is_empty() { + self.push_parameters(&fndecl.args); } self.push(") => "); diff --git a/zap/src/output/typescript/mod.rs b/zap/src/output/typescript/mod.rs index 71a29755..7aa9c9ba 100644 --- a/zap/src/output/typescript/mod.rs +++ b/zap/src/output/typescript/mod.rs @@ -1,4 +1,4 @@ -use crate::config::{Config, Enum, Ty}; +use crate::config::{Config, Enum, Parameter, Ty}; pub mod client; pub mod server; @@ -224,19 +224,24 @@ pub trait Output: ConfigProvider { } } - fn push_parameters(&mut self, types: &[Ty]) { + fn push_parameters(&mut self, parameters: &[Parameter]) { let value = self.get_config().casing.with("Value", "value", "value"); - for (i, ty) in types.iter().enumerate() { + for (i, parameter) in parameters.iter().enumerate() { if i > 0 { self.push(", "); } - self.push(&format!( - "{value}{}", - if i > 0 { (i + 1).to_string() } else { "".to_string() }, - )); - self.push_arg_ty(ty); + if let Some(name) = parameter.name { + self.push(name); + } else { + self.push(&format!( + "{value}{}", + if i > 0 { (i + 1).to_string() } else { "".to_string() }, + )); + } + + self.push_arg_ty(¶meter.ty); } } diff --git a/zap/src/output/typescript/server.rs b/zap/src/output/typescript/server.rs index 398ff719..7d7cf44b 100644 --- a/zap/src/output/typescript/server.rs +++ b/zap/src/output/typescript/server.rs @@ -1,4 +1,3 @@ -use crate::config::Ty; use crate::config::{Config, EvCall, EvDecl, EvSource, TyDecl}; use super::ConfigProvider; @@ -72,9 +71,9 @@ impl<'a> ServerOutput<'a> { self.push_indent(); self.push(&format!("{fire}: ({player}: Player")); - if let Some(types) = &ev.data { + if !ev.data.is_empty() { self.push(", "); - self.push_parameters(types); + self.push_parameters(&ev.data); } self.push(") => void;\n"); @@ -86,8 +85,8 @@ impl<'a> ServerOutput<'a> { self.push_indent(); self.push(&format!("{fire_all}: (")); - if let Some(types) = &ev.data { - self.push_parameters(types); + if !ev.data.is_empty() { + self.push_parameters(&ev.data); } self.push(") => void;\n"); @@ -100,9 +99,9 @@ impl<'a> ServerOutput<'a> { self.push_indent(); self.push(&format!("{fire_except}: ({except}: Player")); - if let Some(types) = &ev.data { + if !ev.data.is_empty() { self.push(", "); - self.push_parameters(types); + self.push_parameters(&ev.data); } self.push(") => void;\n"); @@ -115,9 +114,9 @@ impl<'a> ServerOutput<'a> { self.push_indent(); self.push(&format!("{fire_list}: ({list}: Player[]")); - if let Some(types) = &ev.data { + if !ev.data.is_empty() { self.push(", "); - self.push_parameters(types); + self.push_parameters(&ev.data); } self.push(") => void;\n"); @@ -130,9 +129,9 @@ impl<'a> ServerOutput<'a> { self.push_indent(); self.push(&format!("{fire_set}: ({set}: Set")); - if let Some(types) = &ev.data { + if !ev.data.is_empty() { self.push(", "); - self.push_parameters(types); + self.push_parameters(&ev.data); } self.push(") => void\n"); @@ -187,9 +186,9 @@ impl<'a> ServerOutput<'a> { self.push_indent(); self.push(&format!("{set_callback}: ({callback}: ({player}: Player")); - if let Some(types) = &ev.data { + if !ev.data.is_empty() { self.push(", "); - self.push_parameters(types); + self.push_parameters(&ev.data); } self.push(") => void) => () => void;\n"); @@ -211,9 +210,9 @@ impl<'a> ServerOutput<'a> { self.push_indent(); self.push(&format!("{set_callback}: ({callback}: ({player}: Player")); - if let Some(types) = &fndecl.args { + if !fndecl.args.is_empty() { self.push(", "); - self.push_parameters(types); + self.push_parameters(&fndecl.args); } self.push(") => "); diff --git a/zap/src/parser/convert.rs b/zap/src/parser/convert.rs index 25d9915f..734cc595 100644 --- a/zap/src/parser/convert.rs +++ b/zap/src/parser/convert.rs @@ -1,6 +1,8 @@ use std::collections::{HashMap, HashSet}; -use crate::config::{Casing, Config, Enum, EvDecl, EvType, FnDecl, NumTy, Range, Struct, Ty, TyDecl, YieldType}; +use crate::config::{ + Casing, Config, Enum, EvDecl, EvType, FnDecl, NumTy, Parameter, Range, Struct, Ty, TyDecl, YieldType, +}; use super::{ reports::{Report, Span}, @@ -319,17 +321,24 @@ impl<'src> Converter<'src> { let from = evdecl.from; let evty = evdecl.evty; let call = evdecl.call; - let data = evdecl - .data - .as_ref() - .map(|types| types.iter().map(|ty| self.ty(ty)).collect::>()); + let data = evdecl.data.as_ref().map(|parameters| { + parameters + .parameters + .iter() + .map(|(identifier, ty)| { + let name = identifier.map(|identifier| identifier.name); + + Parameter { name, ty: self.ty(ty) } + }) + .collect::>() + }); if data.is_some() && evty == EvType::Unreliable { let mut min = 0; let mut max = Some(0); - for ty in data.as_ref().unwrap() { - let (ty_min, ty_max) = ty.size(tydecls, &mut HashSet::new()); + for parameter in data.as_ref().unwrap() { + let (ty_min, ty_max) = parameter.ty.size(tydecls, &mut HashSet::new()); min += ty_min; @@ -361,7 +370,7 @@ impl<'src> Converter<'src> { from, evty, call, - data, + data: data.unwrap_or_default(), id, } } @@ -369,10 +378,18 @@ impl<'src> Converter<'src> { fn fndecl(&mut self, fndecl: &SyntaxFnDecl<'src>, id: usize) -> FnDecl<'src> { let name = fndecl.name.name; let call = fndecl.call; - let args = fndecl - .args - .as_ref() - .map(|types| types.iter().map(|ty| self.ty(ty)).collect::>()); + let args = fndecl.args.as_ref().map(|parameters| { + parameters + .parameters + .iter() + .map(|(identifier, ty)| { + let name = identifier.map(|identifier| identifier.name); + + Parameter { name, ty: self.ty(ty) } + }) + .collect::>() + }); + let rets = fndecl .rets .as_ref() @@ -380,7 +397,7 @@ impl<'src> Converter<'src> { FnDecl { name, - args, + args: args.unwrap_or_default(), call, rets, id, diff --git a/zap/src/parser/grammar.lalrpop b/zap/src/parser/grammar.lalrpop index dee0fca0..8ca6ae96 100644 --- a/zap/src/parser/grammar.lalrpop +++ b/zap/src/parser/grammar.lalrpop @@ -43,7 +43,7 @@ Decl: SyntaxDecl<'input> = { FnDecl: SyntaxFnDecl<'input> = { "funct" "=" "{" "call" ":" - )?> + )?> )?> ","? "}" ";"? => SyntaxFnDecl { start, name, call, args, rets, end }, @@ -59,7 +59,7 @@ EvDecl: SyntaxEvDecl<'input> = { "from" ":" "," "type" ":" "," "call" ":" - )?> + )?> ","? "}" ";"? => SyntaxEvDecl { start, name, from, evty, call, data, end }, } @@ -121,6 +121,22 @@ TyList: Vec> = { "(" > ")" => tys, } +Paremeters: SyntaxParameters<'input> = { + + + => SyntaxParameters { start, parameters, end }, +} + +ParameterList: Vec<(Option>, SyntaxTy<'input>)> = { + => vec![(None, ty)], + "(" > ")" => tys, +} + +Parameter: (Option>, SyntaxTy<'input>) = { + ":" => (Some(name), ty), + => (None, ty), +} + Enum: SyntaxEnum<'input> = { => SyntaxEnum { start, kind, end }, } diff --git a/zap/src/parser/syntax_tree.rs b/zap/src/parser/syntax_tree.rs index 9acdd38c..84c6ce6b 100644 --- a/zap/src/parser/syntax_tree.rs +++ b/zap/src/parser/syntax_tree.rs @@ -78,7 +78,7 @@ pub struct SyntaxFnDecl<'src> { pub start: usize, pub name: SyntaxIdentifier<'src>, pub call: FnCall, - pub args: Option>>, + pub args: Option>, pub rets: Option>>, pub end: usize, } @@ -96,7 +96,7 @@ pub struct SyntaxEvDecl<'src> { pub from: EvSource, pub evty: EvType, pub call: EvCall, - pub data: Option>>, + pub data: Option>, pub end: usize, } @@ -106,6 +106,19 @@ impl<'src> Spanned for SyntaxEvDecl<'src> { } } +#[derive(Debug, Clone, PartialEq)] +pub struct SyntaxParameters<'src> { + pub start: usize, + pub parameters: Vec<(Option>, SyntaxTy<'src>)>, + pub end: usize, +} + +impl<'src> Spanned for SyntaxParameters<'src> { + fn span(&self) -> Span { + self.start..self.end + } +} + #[derive(Debug, Clone, PartialEq)] pub struct SyntaxTyDecl<'src> { pub start: usize, From 442851591dc74519f5e367ef13e5441bb7ffcbc4 Mon Sep 17 00:00:00 2001 From: nezuo Date: Fri, 29 Nov 2024 17:40:24 -0800 Subject: [PATCH 2/8] Include names in output --- zap/src/irgen/des.rs | 19 +++------- zap/src/irgen/mod.rs | 2 +- zap/src/irgen/ser.rs | 19 +++------- zap/src/output/luau/client.rs | 42 ++++++++++++++-------- zap/src/output/luau/server.rs | 68 ++++++++++++++++++++++++----------- zap/src/output/mod.rs | 31 ++++++++++++++++ zap/src/output/tooling.rs | 13 ++++--- 7 files changed, 126 insertions(+), 68 deletions(-) diff --git a/zap/src/irgen/des.rs b/zap/src/irgen/des.rs index bb2ff8a4..189487a1 100644 --- a/zap/src/irgen/des.rs +++ b/zap/src/irgen/des.rs @@ -14,21 +14,12 @@ impl Gen for Des { self.buf.push(stmt); } - fn gen<'a, I>(mut self, var: Var, types: I) -> Vec + fn gen<'a, I>(mut self, names: &[String], types: I) -> Vec where I: Iterator>, { - for (i, ty) in types.enumerate() { - let var = if i > 0 { - Var::Name(match &var { - Var::Name(name) => format!("{name}{}", i + 1), - _ => unreachable!(), - }) - } else { - var.clone() - }; - - self.push_ty(ty, var); + for (ty, name) in types.zip(names) { + self.push_ty(ty, Var::Name(name.to_string())); } self.buf @@ -434,7 +425,7 @@ impl Des { } } -pub fn gen<'a, I>(types: I, var: &str, checks: bool) -> Vec +pub fn gen<'a, I>(types: I, names: &[String], checks: bool) -> Vec where I: IntoIterator>, { @@ -443,5 +434,5 @@ where buf: vec![], var_occurrences: HashMap::new(), } - .gen(var.into(), types.into_iter()) + .gen(names, types.into_iter()) } diff --git a/zap/src/irgen/mod.rs b/zap/src/irgen/mod.rs index 1ab5bec8..03786021 100644 --- a/zap/src/irgen/mod.rs +++ b/zap/src/irgen/mod.rs @@ -9,7 +9,7 @@ pub mod ser; pub trait Gen { fn push_stmt(&mut self, stmt: Stmt); - fn gen<'a, I>(self, var: Var, types: I) -> Vec + fn gen<'a, I>(self, names: &[String], types: I) -> Vec where I: Iterator>; diff --git a/zap/src/irgen/ser.rs b/zap/src/irgen/ser.rs index 93b3c7ad..dda6d70f 100644 --- a/zap/src/irgen/ser.rs +++ b/zap/src/irgen/ser.rs @@ -14,21 +14,12 @@ impl Gen for Ser { self.buf.push(stmt); } - fn gen<'a, I>(mut self, var: Var, types: I) -> Vec + fn gen<'a, I>(mut self, names: &[String], types: I) -> Vec where I: Iterator>, { - for (i, ty) in types.enumerate() { - let var = if i > 0 { - Var::Name(match &var { - Var::Name(name) => format!("{name}{}", i + 1), - _ => unreachable!(), - }) - } else { - var.clone() - }; - - self.push_ty(ty, var); + for (ty, name) in types.zip(names) { + self.push_ty(ty, Var::Name(name.to_string())); } self.buf @@ -372,7 +363,7 @@ impl Ser { } } -pub fn gen<'a, I>(types: I, var: &str, checks: bool) -> Vec +pub fn gen<'a, I>(types: I, names: &[String], checks: bool) -> Vec where I: IntoIterator>, { @@ -381,5 +372,5 @@ where buf: vec![], var_occurrences: HashMap::new(), } - .gen(var.into(), types.into_iter()) + .gen(names, types.into_iter()) } diff --git a/zap/src/output/luau/client.rs b/zap/src/output/luau/client.rs index c3121f0e..b558339e 100644 --- a/zap/src/output/luau/client.rs +++ b/zap/src/output/luau/client.rs @@ -1,6 +1,7 @@ use crate::{ config::{Config, EvCall, EvDecl, EvSource, EvType, FnDecl, Parameter, TyDecl, YieldType}, irgen::{des, ser}, + output::{get_named_values, get_unamed_values}, }; use super::Output; @@ -103,14 +104,18 @@ impl<'src> ClientOutput<'src> { self.push_line(&format!("function types.write_{name}(value: {name})")); self.indent(); - self.push_stmts(&ser::gen(&[ty.clone()], "value", self.config.write_checks)); + self.push_stmts(&ser::gen( + &[ty.clone()], + &["value".to_string()], + self.config.write_checks, + )); self.dedent(); self.push_line("end"); self.push_line(&format!("function types.read_{name}()")); self.indent(); self.push_line("local value;"); - self.push_stmts(&des::gen(&[ty.clone()], "value", false)); + self.push_stmts(&des::gen(&[ty.clone()], &["value".to_string()], false)); self.push_line("return value"); self.dedent(); self.push_line("end"); @@ -215,7 +220,11 @@ impl<'src> ClientOutput<'src> { self.push_line(&format!("local {values}")); if !ev.data.is_empty() { - self.push_stmts(&des::gen(ev.data.iter().map(|parameter| ¶meter.ty), "value", true)); + self.push_stmts(&des::gen( + ev.data.iter().map(|parameter| ¶meter.ty), + &get_unamed_values("value", ev.data.len()), + true, + )); } if ev.call == EvCall::SingleSync || ev.call == EvCall::SingleAsync { @@ -309,7 +318,7 @@ impl<'src> ClientOutput<'src> { self.push_line(&format!("local {values}")); if let Some(data) = &fndecl.rets { - self.push_stmts(&des::gen(data, "value", true)); + self.push_stmts(&des::gen(data, &get_unamed_values("value", data.len()), true)); } match self.config.yield_type { @@ -402,7 +411,7 @@ impl<'src> ClientOutput<'src> { if !ev.data.is_empty() { self.push_stmts(&des::gen( ev.data.iter().map(|parameter| ¶meter.ty), - "value", + &get_unamed_values("value", ev.data.len()), self.config.write_checks, )); } @@ -554,17 +563,22 @@ impl<'src> ClientOutput<'src> { fn push_value_parameters(&mut self, parameters: &[Parameter]) { for (i, parameter) in parameters.iter().enumerate() { - let value = format!( - "{}{}", - self.config.casing.with("Value", "value", "value"), - if i == 0 { "".to_string() } else { (i + 1).to_string() } - ); - if i > 0 { self.push(", "); } - self.push(&format!("{value}: ")); + if let Some(name) = parameter.name { + self.push(&format!("{name}: ")); + } else { + let value = format!( + "{}{}", + self.config.casing.with("Value", "value", "value"), + if i == 0 { "".to_string() } else { (i + 1).to_string() } + ); + + self.push(&format!("{value}: ")); + } + self.push_ty(¶meter.ty); } } @@ -593,7 +607,7 @@ impl<'src> ClientOutput<'src> { if !ev.data.is_empty() { self.push_stmts(&ser::gen( ev.data.iter().map(|parameter| ¶meter.ty), - value, + &get_named_values(value, &ev.data), self.config.write_checks, )); } @@ -859,7 +873,7 @@ impl<'src> ClientOutput<'src> { if !fndecl.args.is_empty() { self.push_stmts(&ser::gen( fndecl.args.iter().map(|parameter| ¶meter.ty), - value, + &get_named_values(value, &fndecl.args), self.config.write_checks, )); } diff --git a/zap/src/output/luau/server.rs b/zap/src/output/luau/server.rs index f4f567a3..4d9f57df 100644 --- a/zap/src/output/luau/server.rs +++ b/zap/src/output/luau/server.rs @@ -1,6 +1,7 @@ use crate::{ config::{Config, EvCall, EvDecl, EvSource, EvType, FnCall, FnDecl, Parameter, TyDecl}, irgen::{des, ser}, + output::{get_named_values, get_unamed_values}, }; use super::Output; @@ -115,14 +116,18 @@ impl<'a> ServerOutput<'a> { self.push_line(&format!("function types.write_{name}(value: {name})")); self.indent(); - self.push_stmts(&ser::gen(&[ty.clone()], "value", self.config.write_checks)); + self.push_stmts(&ser::gen( + &[ty.clone()], + &["value".to_string()], + self.config.write_checks, + )); self.dedent(); self.push_line("end"); self.push_line(&format!("function types.read_{name}()")); self.indent(); self.push_line("local value;"); - self.push_stmts(&des::gen(&[ty.clone()], "value", true)); + self.push_stmts(&des::gen(&[ty.clone()], &["value".to_string()], true)); self.push_line("return value"); self.dedent(); self.push_line("end"); @@ -227,7 +232,11 @@ impl<'a> ServerOutput<'a> { self.push_line(&format!("local {values}")); if !ev.data.is_empty() { - self.push_stmts(&des::gen(ev.data.iter().map(|parameter| ¶meter.ty), "value", true)); + self.push_stmts(&des::gen( + ev.data.iter().map(|parameter| ¶meter.ty), + &get_unamed_values("value", ev.data.len()), + true, + )); } if ev.call == EvCall::SingleSync || ev.call == EvCall::SingleAsync { @@ -276,7 +285,7 @@ impl<'a> ServerOutput<'a> { if !fndecl.args.is_empty() { self.push_stmts(&des::gen( fndecl.args.iter().map(|parameter| ¶meter.ty), - "value", + &get_unamed_values("value", fndecl.args.len()), true, )); } @@ -322,8 +331,12 @@ impl<'a> ServerOutput<'a> { self.push_line("alloc(1)"); self.push_line("buffer.writeu8(outgoing_buff, outgoing_apos, call_id_2)"); - if let Some(ty) = &fndecl.rets { - self.push_stmts(&ser::gen(ty, "rets", self.config.write_checks)); + if let Some(types) = &fndecl.rets { + self.push_stmts(&ser::gen( + types, + &get_unamed_values("rets", types.len()), + self.config.write_checks, + )); } self.push_line("player_map[player_2] = save()"); @@ -339,8 +352,12 @@ impl<'a> ServerOutput<'a> { self.push_line("alloc(1)"); self.push_line("buffer.writeu8(outgoing_buff, outgoing_apos, call_id)"); - if let Some(ty) = &fndecl.rets { - self.push_stmts(&ser::gen(ty, "rets", self.config.write_checks)); + if let Some(types) = &fndecl.rets { + self.push_stmts(&ser::gen( + types, + &get_unamed_values("rets", types.len()), + self.config.write_checks, + )); } self.push_line("player_map[player] = save()"); @@ -426,7 +443,11 @@ impl<'a> ServerOutput<'a> { self.push_line(&format!("local {}", values)); if !ev.data.is_empty() { - self.push_stmts(&des::gen(ev.data.iter().map(|parameter| ¶meter.ty), "value", true)); + self.push_stmts(&des::gen( + ev.data.iter().map(|parameter| ¶meter.ty), + &get_unamed_values("value", ev.data.len()), + true, + )); } if ev.call == EvCall::SingleSync || ev.call == EvCall::SingleAsync { @@ -501,17 +522,22 @@ impl<'a> ServerOutput<'a> { fn push_value_parameters(&mut self, parameters: &[Parameter]) { for (i, parameter) in parameters.iter().enumerate() { - let value = format!( - "{}{}", - self.config.casing.with("Value", "value", "value"), - if i == 0 { "".to_string() } else { (i + 1).to_string() } - ); - if i > 0 { self.push(", "); } - self.push(&format!("{value}: ")); + if let Some(name) = parameter.name { + self.push(&format!("{name}: ")); + } else { + let value = format!( + "{}{}", + self.config.casing.with("Value", "value", "value"), + if i == 0 { "".to_string() } else { (i + 1).to_string() } + ); + + self.push(&format!("{value}: ")); + } + self.push_ty(¶meter.ty); } } @@ -544,7 +570,7 @@ impl<'a> ServerOutput<'a> { if !parameters.is_empty() { self.push_stmts(&ser::gen( parameters.iter().map(|parameter| ¶meter.ty), - value, + &get_named_values(value, parameters), self.config.write_checks, )); } @@ -585,7 +611,7 @@ impl<'a> ServerOutput<'a> { if !parameters.is_empty() { self.push_stmts(&ser::gen( parameters.iter().map(|parameter| ¶meter.ty), - value, + &get_named_values(value, parameters), self.config.write_checks, )); } @@ -640,7 +666,7 @@ impl<'a> ServerOutput<'a> { if !parameters.is_empty() { self.push_stmts(&ser::gen( parameters.iter().map(|paramater| ¶mater.ty), - value, + &get_named_values(value, parameters), self.config.write_checks, )); } @@ -707,7 +733,7 @@ impl<'a> ServerOutput<'a> { if !parameters.is_empty() { self.push_stmts(&ser::gen( parameters.iter().map(|parameter| ¶meter.ty), - value, + &get_named_values(value, parameters), self.config.write_checks, )); } @@ -766,7 +792,7 @@ impl<'a> ServerOutput<'a> { if !parameters.is_empty() { self.push_stmts(&ser::gen( parameters.iter().map(|parameter| ¶meter.ty), - value, + &get_named_values(value, parameters), self.config.write_checks, )); } diff --git a/zap/src/output/mod.rs b/zap/src/output/mod.rs index 87750f5e..f84fab57 100644 --- a/zap/src/output/mod.rs +++ b/zap/src/output/mod.rs @@ -1,3 +1,34 @@ +use crate::config::Parameter; + pub mod luau; pub mod tooling; pub mod typescript; + +pub fn get_unamed_values(prefix: &str, count: usize) -> Vec { + (0..count) + .map(|i| { + if i > 0 { + format!("{prefix}{}", i + 1) + } else { + prefix.to_string() + } + }) + .collect() +} + +pub fn get_named_values(default_prefix: &str, parameters: &[Parameter]) -> Vec { + parameters + .iter() + .enumerate() + .map(|(i, parameter)| match parameter.name { + Some(name) => name.to_string(), + None => { + if i > 0 { + format!("{default_prefix}{}", i + 1) + } else { + default_prefix.to_string() + } + } + }) + .collect() +} diff --git a/zap/src/output/tooling.rs b/zap/src/output/tooling.rs index b63688fd..0da00046 100644 --- a/zap/src/output/tooling.rs +++ b/zap/src/output/tooling.rs @@ -1,6 +1,7 @@ use crate::{ config::{Config, EvDecl, FnDecl, Parameter, TyDecl}, irgen::{des, Stmt}, + output::get_unamed_values, Output, }; @@ -115,7 +116,7 @@ impl<'src> ToolingOutput<'src> { self.push_line(&format!("function types.read_{name}()")); self.indent(); self.push_line("local value;"); - self.push_stmts(&des::gen(std::iter::once(ty), "value", true)); + self.push_stmts(&des::gen(std::iter::once(ty), &get_unamed_values("value", 1), true)); self.push_line("return value"); self.dedent(); self.push_line("end"); @@ -169,7 +170,11 @@ impl<'src> ToolingOutput<'src> { self.push_line(&format!("local {values}")); if !ev.data.is_empty() { - self.push_stmts(&des::gen(ev.data.iter().map(|parameter| ¶meter.ty), "value", true)); + self.push_stmts(&des::gen( + ev.data.iter().map(|parameter| ¶meter.ty), + &get_unamed_values("value", ev.data.len()), + true, + )); } self.push_line("table.insert(events, {"); @@ -229,7 +234,7 @@ impl<'src> ToolingOutput<'src> { if !fn_decl.args.is_empty() { self.push_stmts(&des::gen( fn_decl.args.iter().map(|parameter| ¶meter.ty), - "value", + &get_unamed_values("value", fn_decl.args.len()), true, )); } @@ -259,7 +264,7 @@ impl<'src> ToolingOutput<'src> { self.push_line(&format!("local {values}")); if let Some(data) = &fn_decl.rets { - self.push_stmts(&des::gen(data, "value", true)); + self.push_stmts(&des::gen(data, &get_unamed_values("value", data.len()), true)); } self.push_line("table.insert(events, {"); From 8992b0ce52d454a9ec68335b0d5d9ced14dec830 Mon Sep 17 00:00:00 2001 From: nezuo Date: Sat, 30 Nov 2024 14:16:06 -0800 Subject: [PATCH 3/8] Rename get_unamed_values to get_unnamed_values --- zap/src/output/luau/client.rs | 8 ++++---- zap/src/output/luau/server.rs | 12 ++++++------ zap/src/output/mod.rs | 2 +- zap/src/output/tooling.rs | 10 +++++----- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/zap/src/output/luau/client.rs b/zap/src/output/luau/client.rs index b558339e..3a9f10af 100644 --- a/zap/src/output/luau/client.rs +++ b/zap/src/output/luau/client.rs @@ -1,7 +1,7 @@ use crate::{ config::{Config, EvCall, EvDecl, EvSource, EvType, FnDecl, Parameter, TyDecl, YieldType}, irgen::{des, ser}, - output::{get_named_values, get_unamed_values}, + output::{get_named_values, get_unnamed_values}, }; use super::Output; @@ -222,7 +222,7 @@ impl<'src> ClientOutput<'src> { if !ev.data.is_empty() { self.push_stmts(&des::gen( ev.data.iter().map(|parameter| ¶meter.ty), - &get_unamed_values("value", ev.data.len()), + &get_unnamed_values("value", ev.data.len()), true, )); } @@ -318,7 +318,7 @@ impl<'src> ClientOutput<'src> { self.push_line(&format!("local {values}")); if let Some(data) = &fndecl.rets { - self.push_stmts(&des::gen(data, &get_unamed_values("value", data.len()), true)); + self.push_stmts(&des::gen(data, &get_unnamed_values("value", data.len()), true)); } match self.config.yield_type { @@ -411,7 +411,7 @@ impl<'src> ClientOutput<'src> { if !ev.data.is_empty() { self.push_stmts(&des::gen( ev.data.iter().map(|parameter| ¶meter.ty), - &get_unamed_values("value", ev.data.len()), + &get_unnamed_values("value", ev.data.len()), self.config.write_checks, )); } diff --git a/zap/src/output/luau/server.rs b/zap/src/output/luau/server.rs index 4d9f57df..5ea4fefd 100644 --- a/zap/src/output/luau/server.rs +++ b/zap/src/output/luau/server.rs @@ -1,7 +1,7 @@ use crate::{ config::{Config, EvCall, EvDecl, EvSource, EvType, FnCall, FnDecl, Parameter, TyDecl}, irgen::{des, ser}, - output::{get_named_values, get_unamed_values}, + output::{get_named_values, get_unnamed_values}, }; use super::Output; @@ -234,7 +234,7 @@ impl<'a> ServerOutput<'a> { if !ev.data.is_empty() { self.push_stmts(&des::gen( ev.data.iter().map(|parameter| ¶meter.ty), - &get_unamed_values("value", ev.data.len()), + &get_unnamed_values("value", ev.data.len()), true, )); } @@ -285,7 +285,7 @@ impl<'a> ServerOutput<'a> { if !fndecl.args.is_empty() { self.push_stmts(&des::gen( fndecl.args.iter().map(|parameter| ¶meter.ty), - &get_unamed_values("value", fndecl.args.len()), + &get_unnamed_values("value", fndecl.args.len()), true, )); } @@ -334,7 +334,7 @@ impl<'a> ServerOutput<'a> { if let Some(types) = &fndecl.rets { self.push_stmts(&ser::gen( types, - &get_unamed_values("rets", types.len()), + &get_unnamed_values("rets", types.len()), self.config.write_checks, )); } @@ -355,7 +355,7 @@ impl<'a> ServerOutput<'a> { if let Some(types) = &fndecl.rets { self.push_stmts(&ser::gen( types, - &get_unamed_values("rets", types.len()), + &get_unnamed_values("rets", types.len()), self.config.write_checks, )); } @@ -445,7 +445,7 @@ impl<'a> ServerOutput<'a> { if !ev.data.is_empty() { self.push_stmts(&des::gen( ev.data.iter().map(|parameter| ¶meter.ty), - &get_unamed_values("value", ev.data.len()), + &get_unnamed_values("value", ev.data.len()), true, )); } diff --git a/zap/src/output/mod.rs b/zap/src/output/mod.rs index f84fab57..493c1cf2 100644 --- a/zap/src/output/mod.rs +++ b/zap/src/output/mod.rs @@ -4,7 +4,7 @@ pub mod luau; pub mod tooling; pub mod typescript; -pub fn get_unamed_values(prefix: &str, count: usize) -> Vec { +pub fn get_unnamed_values(prefix: &str, count: usize) -> Vec { (0..count) .map(|i| { if i > 0 { diff --git a/zap/src/output/tooling.rs b/zap/src/output/tooling.rs index 0da00046..10ffb5da 100644 --- a/zap/src/output/tooling.rs +++ b/zap/src/output/tooling.rs @@ -1,7 +1,7 @@ use crate::{ config::{Config, EvDecl, FnDecl, Parameter, TyDecl}, irgen::{des, Stmt}, - output::get_unamed_values, + output::get_unnamed_values, Output, }; @@ -116,7 +116,7 @@ impl<'src> ToolingOutput<'src> { self.push_line(&format!("function types.read_{name}()")); self.indent(); self.push_line("local value;"); - self.push_stmts(&des::gen(std::iter::once(ty), &get_unamed_values("value", 1), true)); + self.push_stmts(&des::gen(std::iter::once(ty), &get_unnamed_values("value", 1), true)); self.push_line("return value"); self.dedent(); self.push_line("end"); @@ -172,7 +172,7 @@ impl<'src> ToolingOutput<'src> { if !ev.data.is_empty() { self.push_stmts(&des::gen( ev.data.iter().map(|parameter| ¶meter.ty), - &get_unamed_values("value", ev.data.len()), + &get_unnamed_values("value", ev.data.len()), true, )); } @@ -234,7 +234,7 @@ impl<'src> ToolingOutput<'src> { if !fn_decl.args.is_empty() { self.push_stmts(&des::gen( fn_decl.args.iter().map(|parameter| ¶meter.ty), - &get_unamed_values("value", fn_decl.args.len()), + &get_unnamed_values("value", fn_decl.args.len()), true, )); } @@ -264,7 +264,7 @@ impl<'src> ToolingOutput<'src> { self.push_line(&format!("local {values}")); if let Some(data) = &fn_decl.rets { - self.push_stmts(&des::gen(data, &get_unamed_values("value", data.len()), true)); + self.push_stmts(&des::gen(data, &get_unnamed_values("value", data.len()), true)); } self.push_line("table.insert(events, {"); From 82f0cae3b3d437dad4814e6a658fbdcff010799b Mon Sep 17 00:00:00 2001 From: nezuo Date: Sat, 30 Nov 2024 14:24:44 -0800 Subject: [PATCH 4/8] Add docs for named parameters --- docs/config/events.md | 18 +++++++++++------- docs/config/functions.md | 31 +++++++++++++++++++++---------- docs/intro/getting-started.md | 14 ++++---------- docs/usage/events.md | 10 +++++----- 4 files changed, 41 insertions(+), 32 deletions(-) diff --git a/docs/config/events.md b/docs/config/events.md index e63e9bf1..c35f9bac 100644 --- a/docs/config/events.md +++ b/docs/config/events.md @@ -3,17 +3,21 @@ const example = `event MyEvent = { from: Server, type: Reliable, call: ManyAsync, - data: struct { - foo: string, - bar: u8, - }, + data: (Foo: boolean, Bar: u32, Baz: string) }` -const dataExample = `event MyEvent = { +const dataExample = `event OneUnnamedParameter = { from: Server, type: Reliable, call: ManyAsync, - data: (boolean, u32, string) + data: boolean +} + +event TwoUnnamedParameters = { + from: Server, + type: Reliable, + call: ManyAsync, + data: (boolean, u32) }` @@ -65,6 +69,6 @@ Use synchronous events with extreme caution. This field determines the data that is sent with the event. It can be any [Zap type](./types.md). - If the event does not require any data, the `data` field should be excluded. -- You can pass multiple arguments to the event by separating each type with a comma and wrapping them all in parentheses: +- Parameter names and parentheses are optional to preserve backwards compatibility. If parantheses are excluded, the event can only have one unnamed parameter. diff --git a/docs/config/functions.md b/docs/config/functions.md index 1b9132c5..1d73b917 100644 --- a/docs/config/functions.md +++ b/docs/config/functions.md @@ -1,17 +1,27 @@ @@ -48,15 +58,16 @@ Use synchronous functions with extreme caution. This field determines the data that is sent to the server. It can be any [Zap type](./types.md). - If the client doesn't send any data, the `args` field should be excluded. -- You can pass multiple arguments to the function by separating each type with a comma and wrapping them all in parentheses: +- Parameter names and parentheses are optional to preserve backwards compatibility. If parantheses are excluded, the function can only have one unnamed parameter. - + ### `rets` This field determines the data that is sent back to the client from the server. It can be any [Zap type](./types.md). - If the server doesn't return any data, the `rets` field should be excluded. +- Unlike `args`, `rets` cannot be named. - The function can return multiple values by separating each type with a comma and wrapping them all in parentheses: - + diff --git a/docs/intro/getting-started.md b/docs/intro/getting-started.md index d92a2e55..e7170a70 100644 --- a/docs/intro/getting-started.md +++ b/docs/intro/getting-started.md @@ -7,25 +7,19 @@ event MyEvent = { from: Server, type: Reliable, call: ManyAsync, - data: struct { - foo: u32, - bar: string, - }, + data: (Foo: u32, Bar: string), }` const apiExample = `-- Server local Zap = require(path.to.server.output) -Zap.MyEvent.FireAll({ - foo = 123, - bar = "hello world", -}) +Zap.MyEvent.FireAll(123, "hello world") -- Client local Zap = require(path.to.client.output) -Zap.MyEvent.On(function(data) - print(data.foo, data.bar) +Zap.MyEvent.On(function(Foo, Bar) + print(Foo, Bar) end)` diff --git a/docs/usage/events.md b/docs/usage/events.md index 79f3f481..8dd5580b 100644 --- a/docs/usage/events.md +++ b/docs/usage/events.md @@ -3,17 +3,17 @@ const configFile = `event MyEvent = { from: Server, type: Reliable, call: ManyAsync, - data: struct { + data: (Options: struct { foo: string, bar: u8, - }, + }), } event AnotherEvent = { from: Client, type: Reliable, call: SingleAsync, - data: (boolean, u8) + data: (Foo: boolean, Bar: u8) }` @@ -48,7 +48,7 @@ If your event's [call field](../config/events.md#call) is `SingleAsync` or `Sing local Zap = require(Path.To.Zap) -- only server listeners are given the player argument -Zap.AnotherEvent.SetCallback(function(Player, Bool, Number) +Zap.AnotherEvent.SetCallback(function(Player, Foo, Bar) -- Do something with the player and data end) ``` @@ -58,7 +58,7 @@ If your event's [call field](../config/events.md#call) is `ManyAsync` or `ManySy ```lua local Zap = require(Path.To.Zap) -local Disconnect = Zap.MyEvent.On(function(Data) +local Disconnect = Zap.MyEvent.On(function(Options) -- Do something with the data end) From 0f3ba612b0a47dc6e4234aa4c204977c37f74b39 Mon Sep 17 00:00:00 2001 From: nezuo Date: Sat, 30 Nov 2024 16:30:46 -0800 Subject: [PATCH 5/8] Fix typo --- zap/src/parser/grammar.lalrpop | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zap/src/parser/grammar.lalrpop b/zap/src/parser/grammar.lalrpop index 8ca6ae96..0e279be3 100644 --- a/zap/src/parser/grammar.lalrpop +++ b/zap/src/parser/grammar.lalrpop @@ -43,7 +43,7 @@ Decl: SyntaxDecl<'input> = { FnDecl: SyntaxFnDecl<'input> = { "funct" "=" "{" "call" ":" - )?> + )?> )?> ","? "}" ";"? => SyntaxFnDecl { start, name, call, args, rets, end }, @@ -59,7 +59,7 @@ EvDecl: SyntaxEvDecl<'input> = { "from" ":" "," "type" ":" "," "call" ":" - )?> + )?> ","? "}" ";"? => SyntaxEvDecl { start, name, from, evty, call, data, end }, } @@ -121,7 +121,7 @@ TyList: Vec> = { "(" > ")" => tys, } -Paremeters: SyntaxParameters<'input> = { +Parameters: SyntaxParameters<'input> = { => SyntaxParameters { start, parameters, end }, From 1fd636aff4fc3da40c853ced09a48b3943c62684 Mon Sep 17 00:00:00 2001 From: nezuo Date: Sat, 30 Nov 2024 18:38:56 -0800 Subject: [PATCH 6/8] Add error for duplicate parameters --- zap/src/parser/convert.rs | 17 +++++++++++++++++ zap/src/parser/reports.rs | 19 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/zap/src/parser/convert.rs b/zap/src/parser/convert.rs index 734cc595..1c4e5457 100644 --- a/zap/src/parser/convert.rs +++ b/zap/src/parser/convert.rs @@ -333,6 +333,23 @@ impl<'src> Converter<'src> { .collect::>() }); + if let Some(syntax_parameters) = &evdecl.data { + let mut seen: HashMap<_, std::ops::Range> = HashMap::new(); + for (identifier, _) in &syntax_parameters.parameters { + if let Some(identifier) = identifier { + if let Some(first_span) = seen.get(identifier.name) { + self.report(Report::AnalyzeDuplicateParameter { + prev_span: first_span.clone(), + dup_span: identifier.span(), + name: identifier.name, + }); + } else { + seen.insert(identifier.name, identifier.span()); + } + } + } + } + if data.is_some() && evty == EvType::Unreliable { let mut min = 0; let mut max = Some(0); diff --git a/zap/src/parser/reports.rs b/zap/src/parser/reports.rs index bf02dc38..267973fd 100644 --- a/zap/src/parser/reports.rs +++ b/zap/src/parser/reports.rs @@ -96,6 +96,12 @@ pub enum Report<'src> { dup_span: Span, name: &'src str, }, + + AnalyzeDuplicateParameter { + prev_span: Span, + dup_span: Span, + name: &'src str, + }, } impl<'src> Report<'src> { @@ -122,6 +128,7 @@ impl<'src> Report<'src> { Self::AnalyzeUnboundedRecursiveType { .. } => Severity::Error, Self::AnalyzeMissingOptValue { .. } => Severity::Error, Self::AnalyzeDuplicateDecl { .. } => Severity::Error, + Self::AnalyzeDuplicateParameter { .. } => Severity::Error, } } @@ -151,6 +158,7 @@ impl<'src> Report<'src> { Self::AnalyzeUnboundedRecursiveType { .. } => "unbounded recursive type".to_string(), Self::AnalyzeMissingOptValue { .. } => "missing option expected".to_string(), Self::AnalyzeDuplicateDecl { name, .. } => format!("duplicate declaration '{}'", name), + Self::AnalyzeDuplicateParameter { name, .. } => format!("duplicate parameter '{}'", name), } } @@ -177,6 +185,7 @@ impl<'src> Report<'src> { Self::AnalyzeUnboundedRecursiveType { .. } => "3012", Self::AnalyzeMissingOptValue { .. } => "3013", Self::AnalyzeDuplicateDecl { .. } => "3014", + Self::AnalyzeDuplicateParameter { .. } => "3015", } } @@ -272,6 +281,15 @@ impl<'src> Report<'src> { Label::primary((), dup_span.clone()).with_message("duplicate declaration"), ] } + + Self::AnalyzeDuplicateParameter { + prev_span, dup_span, .. + } => { + vec![ + Label::secondary((), prev_span.clone()).with_message("first parameter"), + Label::primary((), dup_span.clone()).with_message("duplicate parameter"), + ] + } } } @@ -335,6 +353,7 @@ impl<'src> Report<'src> { "the {expected} option should not be empty if {required_when}" )]), Self::AnalyzeDuplicateDecl { .. } => None, + Self::AnalyzeDuplicateParameter { .. } => None, } } From 7f258d0fdd39ff9825bcd6bb260793c345a3e7eb Mon Sep 17 00:00:00 2001 From: nezuo Date: Sat, 30 Nov 2024 18:41:57 -0800 Subject: [PATCH 7/8] Add duplicate parameter error to functions --- zap/src/parser/convert.rs | 42 +++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/zap/src/parser/convert.rs b/zap/src/parser/convert.rs index 1c4e5457..f1e3c5d0 100644 --- a/zap/src/parser/convert.rs +++ b/zap/src/parser/convert.rs @@ -311,12 +311,33 @@ impl<'src> Converter<'src> { } } + fn check_duplicate_parameters(&mut self, syntax_parameters: &SyntaxParameters<'src>) { + let mut seen: HashMap<_, std::ops::Range> = HashMap::new(); + for (identifier, _) in &syntax_parameters.parameters { + if let Some(identifier) = identifier { + if let Some(first_span) = seen.get(identifier.name) { + self.report(Report::AnalyzeDuplicateParameter { + prev_span: first_span.clone(), + dup_span: identifier.span(), + name: identifier.name, + }); + } else { + seen.insert(identifier.name, identifier.span()); + } + } + } + } + fn evdecl( &mut self, evdecl: &SyntaxEvDecl<'src>, id: usize, tydecls: &HashMap<&'src str, &Ty<'src>>, ) -> EvDecl<'src> { + if let Some(syntax_parameters) = &evdecl.data { + self.check_duplicate_parameters(syntax_parameters); + } + let name = evdecl.name.name; let from = evdecl.from; let evty = evdecl.evty; @@ -333,23 +354,6 @@ impl<'src> Converter<'src> { .collect::>() }); - if let Some(syntax_parameters) = &evdecl.data { - let mut seen: HashMap<_, std::ops::Range> = HashMap::new(); - for (identifier, _) in &syntax_parameters.parameters { - if let Some(identifier) = identifier { - if let Some(first_span) = seen.get(identifier.name) { - self.report(Report::AnalyzeDuplicateParameter { - prev_span: first_span.clone(), - dup_span: identifier.span(), - name: identifier.name, - }); - } else { - seen.insert(identifier.name, identifier.span()); - } - } - } - } - if data.is_some() && evty == EvType::Unreliable { let mut min = 0; let mut max = Some(0); @@ -393,6 +397,10 @@ impl<'src> Converter<'src> { } fn fndecl(&mut self, fndecl: &SyntaxFnDecl<'src>, id: usize) -> FnDecl<'src> { + if let Some(syntax_parameters) = &fndecl.args { + self.check_duplicate_parameters(syntax_parameters); + } + let name = fndecl.name.name; let call = fndecl.call; let args = fndecl.args.as_ref().map(|parameters| { From ad76696fe9efb5e59be588de86dc71b7ba7bb3bc Mon Sep 17 00:00:00 2001 From: nezuo Date: Sun, 1 Dec 2024 12:04:30 -0800 Subject: [PATCH 8/8] Improve error for named rets --- zap/src/parser/convert.rs | 21 +++++++++++++++++---- zap/src/parser/grammar.lalrpop | 7 +------ zap/src/parser/reports.rs | 12 ++++++++++++ zap/src/parser/syntax_tree.rs | 2 +- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/zap/src/parser/convert.rs b/zap/src/parser/convert.rs index f1e3c5d0..957be2d1 100644 --- a/zap/src/parser/convert.rs +++ b/zap/src/parser/convert.rs @@ -401,6 +401,16 @@ impl<'src> Converter<'src> { self.check_duplicate_parameters(syntax_parameters); } + if let Some(syntax_parameters) = &fndecl.rets { + for parameter in &syntax_parameters.parameters { + if let Some(identifier) = parameter.0 { + self.report(Report::AnalyzeNamedReturn { + name_span: identifier.span(), + }); + } + } + } + let name = fndecl.name.name; let call = fndecl.call; let args = fndecl.args.as_ref().map(|parameters| { @@ -415,10 +425,13 @@ impl<'src> Converter<'src> { .collect::>() }); - let rets = fndecl - .rets - .as_ref() - .map(|types| types.iter().map(|ty| self.ty(ty)).collect::>()); + let rets = fndecl.rets.as_ref().map(|parameters| { + parameters + .parameters + .iter() + .map(|(_, ty)| self.ty(ty)) + .collect::>() + }); FnDecl { name, diff --git a/zap/src/parser/grammar.lalrpop b/zap/src/parser/grammar.lalrpop index 0e279be3..73abf904 100644 --- a/zap/src/parser/grammar.lalrpop +++ b/zap/src/parser/grammar.lalrpop @@ -44,7 +44,7 @@ FnDecl: SyntaxFnDecl<'input> = { "funct" "=" "{" "call" ":" )?> - )?> + )?> ","? "}" ";"? => SyntaxFnDecl { start, name, call, args, rets, end }, } @@ -116,11 +116,6 @@ TyKind: SyntaxTyKind<'input> = { "Instance" ")")?> => SyntaxTyKind::Instance(c), } -TyList: Vec> = { - => vec![ty], - "(" > ")" => tys, -} - Parameters: SyntaxParameters<'input> = { diff --git a/zap/src/parser/reports.rs b/zap/src/parser/reports.rs index 267973fd..79e2f376 100644 --- a/zap/src/parser/reports.rs +++ b/zap/src/parser/reports.rs @@ -102,6 +102,10 @@ pub enum Report<'src> { dup_span: Span, name: &'src str, }, + + AnalyzeNamedReturn { + name_span: Span, + }, } impl<'src> Report<'src> { @@ -129,6 +133,7 @@ impl<'src> Report<'src> { Self::AnalyzeMissingOptValue { .. } => Severity::Error, Self::AnalyzeDuplicateDecl { .. } => Severity::Error, Self::AnalyzeDuplicateParameter { .. } => Severity::Error, + Self::AnalyzeNamedReturn { .. } => Severity::Error, } } @@ -159,6 +164,7 @@ impl<'src> Report<'src> { Self::AnalyzeMissingOptValue { .. } => "missing option expected".to_string(), Self::AnalyzeDuplicateDecl { name, .. } => format!("duplicate declaration '{}'", name), Self::AnalyzeDuplicateParameter { name, .. } => format!("duplicate parameter '{}'", name), + Self::AnalyzeNamedReturn { .. } => "rets cannot be named".to_string(), } } @@ -186,6 +192,7 @@ impl<'src> Report<'src> { Self::AnalyzeMissingOptValue { .. } => "3013", Self::AnalyzeDuplicateDecl { .. } => "3014", Self::AnalyzeDuplicateParameter { .. } => "3015", + Self::AnalyzeNamedReturn { .. } => "3016", } } @@ -290,6 +297,10 @@ impl<'src> Report<'src> { Label::primary((), dup_span.clone()).with_message("duplicate parameter"), ] } + + Self::AnalyzeNamedReturn { name_span } => { + vec![Label::primary((), name_span.clone()).with_message("must be removed")] + } } } @@ -354,6 +365,7 @@ impl<'src> Report<'src> { )]), Self::AnalyzeDuplicateDecl { .. } => None, Self::AnalyzeDuplicateParameter { .. } => None, + Self::AnalyzeNamedReturn { .. } => None, } } diff --git a/zap/src/parser/syntax_tree.rs b/zap/src/parser/syntax_tree.rs index 84c6ce6b..0d77b111 100644 --- a/zap/src/parser/syntax_tree.rs +++ b/zap/src/parser/syntax_tree.rs @@ -79,7 +79,7 @@ pub struct SyntaxFnDecl<'src> { pub name: SyntaxIdentifier<'src>, pub call: FnCall, pub args: Option>, - pub rets: Option>>, + pub rets: Option>, pub end: usize, }