esl_compiler/builder/
variable.rs1use crate::builder::subject::{build_some_subject, Subject};
4use crate::context::Context;
5use crate::cursor::{Cursor, Error, Token};
6use crate::location::FileLocation;
7use crate::parser::Rule;
8use crate::reference::{Reference, TypeDefinitionTarget, VariableTarget};
9
10#[derive(Clone, Debug, PartialEq)]
12pub struct Variable {
13 pub name: Token,
15 pub loc: FileLocation,
17 pub definition: Reference<Token, TypeDefinitionTarget>,
19 pub is_property: bool,
21}
22impl std::fmt::Display for Variable {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 write!(f, "{}", self.name)
25 }
26}
27
28#[derive(Clone, Debug, PartialEq)]
30pub struct VariableGroup {
31 pub name: Token,
33 pub loc: FileLocation,
35 pub members: Vec<Reference<Subject, VariableTarget>>,
37}
38impl std::fmt::Display for VariableGroup {
39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 write!(f, "{}", self.name)
41 }
42}
43
44#[derive(Clone, Debug, PartialEq)]
46pub struct UnboundedVariable {
47 pub name: Token,
49 pub loc: FileLocation,
51 pub definition: Reference<Token, TypeDefinitionTarget>,
53}
54impl std::fmt::Display for UnboundedVariable {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 write!(f, "{}", self.name)
57 }
58}
59
60pub fn build_variable_declaration(
62 ctx: &mut Context,
63 variable_declaration: Cursor,
64 is_property: bool,
65) -> Result<Vec<Variable>, Error> {
66 let mut variables = vec![];
67 let mut cs = variable_declaration.into_inner();
68
69 let some_names = cs.req_first(Rule::some_names)?;
70
71 let some_type = cs.req_first(Rule::some_type)?;
72 let definition = Reference::new(some_type.into());
73
74 for some_name in some_names.into_inner().get_all(Rule::some_name) {
75 let name = some_name.into();
76 variables.push(Variable {
77 name,
78 loc: cs.as_location(),
79 definition: definition.clone(),
80 is_property,
81 });
82 }
83
84 Ok(variables)
85}
86
87pub fn build_parameter_declaration(
89 ctx: &mut Context,
90 parameter_declaration: Cursor,
91) -> Result<Vec<Variable>, Error> {
92 let mut cs = parameter_declaration.into_inner();
93 let variable_declaration = cs.req_first(Rule::variable_declaration)?;
94 let is_property = cs.find_first(Rule::kw_class_property).is_some();
95 build_variable_declaration(ctx, variable_declaration, is_property)
96}
97
98pub fn build_variable_group_declaration(
100 ctx: &mut Context,
101 variable_group_line: Cursor,
102) -> Result<Vec<VariableGroup>, Error> {
103 let mut groups = vec![];
104 let mut cs = variable_group_line.into_inner();
105
106 let some_names = cs.req_first(Rule::some_names)?;
107
108 let mut members = vec![];
109 let arguments = cs.req_first(Rule::arguments)?;
110 for some_variable in arguments.into_inner().get_all(Rule::some_variable) {
111 members.push(build_some_variable(ctx, some_variable)?);
112 }
113
114 for some_name in some_names.into_inner().get_all(Rule::some_name) {
115 let name = some_name.into();
116 groups.push(VariableGroup {
117 name,
118 loc: cs.as_location(),
119 members: members.clone(),
120 })
121 }
122
123 Ok(groups)
124}
125
126pub fn build_variable_unbounded_declaration(
128 ctx: &mut Context,
129 variable_line_unbounded: Cursor,
130) -> Result<UnboundedVariable, Error> {
131 let mut cs = variable_line_unbounded.into_inner();
132 let name = cs
133 .req_first(Rule::some_name)
134 .map(|some_name| some_name.into())?;
135
136 let some_type = cs.req_first(Rule::some_type)?;
137 let definition = Reference::new(some_type.into());
138 Ok(UnboundedVariable {
139 name,
140 loc: cs.as_location(),
141 definition,
142 })
143}
144
145pub fn build_some_variables(
147 ctx: &mut Context,
148 some_variables: Cursor,
149) -> Result<Vec<Reference<Subject, VariableTarget>>, Error> {
150 some_variables
151 .into_inner()
152 .get_all(Rule::some_variable)
153 .map(|c| build_some_variable(ctx, c))
154 .collect()
155}
156
157pub fn build_some_variable(
159 ctx: &mut Context,
160 some_variable: Cursor,
161) -> Result<Reference<Subject, VariableTarget>, Error> {
162 let reference = some_variable
163 .into_inner()
164 .req_first(Rule::some_subject)
165 .and_then(|c| build_some_subject(ctx, c))?
166 .into();
167 Ok(reference)
168}