1use super::*;
2use argumenti::*;
3
4impl<'a> Parser<'a> {
5 pub fn funkcija(&mut self, ime: &Token, izraz: &[Token]) -> Result<Rc<Vozlišče>, Napake> {
6 let (_, _, izraz) = loči_spredaj(izraz, &["("])
7 .ok_or(Napake::from_zaporedje(izraz, E5, "Pričakovan '('"))??;
8 let (parametri_izraz, _, izraz) = loči_spredaj(izraz, &[")"])
9 .ok_or(Napake::from_zaporedje(izraz, E5, "Pričakovan ')'"))??;
10 let (tip_izraz, oklepaj, izraz) = loči_spredaj(izraz, &["{"])
11 .ok_or(Napake::from_zaporedje(izraz, E5, "Pričakovan '{'"))??;
12
13 let tip = match tip_izraz {
14 [] => Ok(Tip::Brez),
15 [Ločilo("->", ..)] => Err(Napake::from_zaporedje(&[*oklepaj], E5, "Za '->' pričakovan tip")),
16 [Ločilo("->", ..), ostanek @ ..] => Tip::from(ostanek),
17 _ => Err(Napake::from_zaporedje(tip_izraz, E5, "Pričakovan '-> <tip>'")),
18 }?;
19
20 let (telo, _, prazno) = loči_zadaj(izraz, &["}"])
21 .ok_or(Napake::from_zaporedje(izraz, E5, "Pričakovan '}'"))??;
22
23 if prazno != [] {
24 return Err(Napake::from_zaporedje(prazno, E3, "Izraz funkcije se mora zaključiti z '}'"));
25 }
26
27 let vrni = Spremenljivka { tip: tip.clone(), ime: "0_vrni".to_string(), naslov: 0, z_odmikom: true }.rc();
28 let pc = Spremenljivka { tip: Tip::Celo, ime: "0_PC".to_string(), naslov: vrni.sprememba_stacka(), z_odmikom: true }.rc();
29
30 let mut spr_funkcije = HashMap::from([
31 ("0_vrni".to_string(), vrni.clone()),
32 ("0_PC".to_string(), pc.clone()),
33 ]);
34
35 let mut naslov_nove = vrni.sprememba_stacka() + pc.sprememba_stacka();
36
37 let mut parametri = Vec::new();
38 let mut napake = Napake::new();
39
40 for parameter in parametri_izraz.split(|p| if let Ločilo(",", ..) = p { true } else { false }) {
41 match parameter {
43 [] => break,
44 [Ime(..)] => (),
45 _ => _ = napake.add_napaka(Napaka::from_zaporedje(parameter, E3, "Neveljavno ime parametra")),
46 }
47
48 let (ime, dvopičje, tip) = loči_spredaj(parameter, &[":"])
49 .ok_or(Napake::from_zaporedje(parameter, E5, "Pričakovano ':'"))??;
50
51 if tip == [] {
52 return Err(Napake::from_zaporedje(&[*dvopičje], E5, "Za ':' pričakovan tip"))
53 }
54
55 let ime = &ime[0];
56 let tip = Tip::from(tip)?;
57
58 if spr_funkcije.contains_key(ime.as_str()) {
59 return Err(Napake::from_zaporedje(&[*ime], E7, "Imena parametrov morajo biti unikatna"))
60 }
61 else {
62 let spr = Spremenljivka { tip: tip.clone(), ime: ime.to_string(), naslov: naslov_nove, z_odmikom: true }.rc();
63 spr_funkcije.insert(ime.to_string(), spr.clone());
64 parametri.push(spr);
65 naslov_nove += tip.sprememba_stacka();
66 }
67 }
68
69 let podpis_funkcije = Self::podpis_funkcije(ime, parametri.iter().map(|p| p.tip()).collect::<Vec<Tip>>().as_slice());
70 spr_funkcije.insert("0_OF".to_string(), Spremenljivka { tip: Tip::Celo, ime: "0_OF".to_string(), naslov: naslov_nove, z_odmikom: true }.rc());
71
72 let mut okolje_funkcije = Parser {
73 spremenljivke_stack: self.spremenljivke_stack.clone(),
74 funkcije_stack: self.funkcije_stack.clone(),
75 reference_stack: self.reference_stack.clone(),
76 spremenljivke: self.spremenljivke.clone(),
77 funkcije: self.funkcije.clone(),
78 št_klicev: self.št_klicev.clone(),
79 reference: self.reference.clone(),
80 znotraj_funkcije: true,
81 };
82
83 okolje_funkcije.spremenljivke_stack.push(spr_funkcije.clone());
84 okolje_funkcije.spremenljivke.extend(spr_funkcije);
85 okolje_funkcije.funkcije.insert(podpis_funkcije.clone(), Funkcija {
86 tip: tip.clone(),
87 ime: podpis_funkcije.clone(),
88 parametri: parametri.clone(),
89 telo: Prazno.rc(),
90 prostor: 0,
91 }.rc());
92
93 let telo = okolje_funkcije.zaporedje(telo)?;
94 let spr_funkcije = okolje_funkcije.spremenljivke_stack.last().unwrap();
95 let prostor = spr_funkcije.values().map(|s| s.sprememba_stacka()).sum::<i32>()
96 - spr_funkcije["0_vrni"].sprememba_stacka()
97 - spr_funkcije["0_PC"].sprememba_stacka()
98 - parametri.iter().map(|p| p.sprememba_stacka()).sum::<i32>()
99 - spr_funkcije["0_OF"].sprememba_stacka();
100 let fun = Funkcija { tip, ime: podpis_funkcije.clone(), parametri, telo, prostor }.rc();
101
102 for (podpis, št_klicev) in okolje_funkcije.št_klicev {
103 match self.št_klicev.get_mut(&podpis) {
104 Some(št) => *št += št_klicev,
105 None => { self.št_klicev.insert(podpis, št_klicev); }
106 }
107 }
108
109 self.funkcije_stack.last_mut().unwrap().insert(podpis_funkcije.clone(), fun.clone());
110 self.funkcije.insert(podpis_funkcije, fun.clone());
111 Ok(fun)
112 }
113
114 pub fn funkcijski_klic_zavrzi_izhod(&mut self, ime: &Token, argumenti: &[Token<'a>]) -> Result<Rc<Vozlišče>, Napake> {
115 let klic = self.funkcijski_klic(ime, argumenti)?;
116 let velikost = klic.tip().sprememba_stacka();
117
118 Ok(Zaporedje(vec![
119 klic,
120 Pop(velikost).rc(),
121 ]).rc())
122 }
123
124 pub fn funkcijski_klic<'b>(&mut self, ime: &Token, argumenti: &'b[Token<'a>]) -> Result<Rc<Vozlišče>, Napake> {
125 let Argumenti { tipi, spremenljivke, argumenti } = self.argumenti(argumenti)?;
126 let podpis_funkcije = Self::podpis_funkcije(ime, tipi.as_slice());
127
128 let funkcija = self.funkcije.get(&podpis_funkcije)
129 .ok_or(Napake::from_zaporedje(&[*ime], E2, &format!("Funkcija '{podpis_funkcije}' ne obstaja")))?
130 .clone();
131
132 match self.št_klicev.get_mut(&podpis_funkcije) {
133 Some(št_klicev) => *št_klicev += 1,
134 None => { self.št_klicev.insert(podpis_funkcije, 1); },
135 }
136
137 Ok(FunkcijskiKlic { funkcija, spremenljivke: Zaporedje(spremenljivke).rc(), argumenti: Zaporedje(argumenti).rc() }.rc())
138 }
139
140 pub fn multi_klic<'b>(&mut self, ime: &'b Token<'a>, argumenti_izraz: &'b [Token<'a>]) -> Result<Rc<Vozlišče>, Napake> where 'a: 'b {
141 let Argumenti { tipi, spremenljivke, argumenti } = self.argumenti(argumenti_izraz)?;
142 let mut funkcijski_klici: Vec<Rc<Vozlišče>> = Vec::new();
143 let mut napake = Napake::new();
144
145 for (tip, (spremenljivka, argument)) in iter::zip(tipi, iter::zip(spremenljivke, argumenti)) {
146 let podpis_funkcije = Self::podpis_funkcije(ime, &[tip]);
147 let funkcija = self.funkcije.get(&podpis_funkcije);
148
149 match funkcija {
150 Some(funkcija) => {
151 funkcijski_klici.push(FunkcijskiKlic {
152 funkcija: funkcija.clone(),
153 spremenljivke: Zaporedje(vec![spremenljivka.rc()]).rc(),
154 argumenti: Zaporedje(vec![argument.rc()]).rc(),
155 }.rc());
156
157 match self.št_klicev.get_mut(&podpis_funkcije) {
158 Some(št_klicev) => *št_klicev += 1,
159 None => { self.št_klicev.insert(podpis_funkcije, 1); },
160 }
161 },
162 None => {
163 napake.add_napaka(Napaka::from_zaporedje(&[*ime], E2,
164 &format!("Funkcija '{podpis_funkcije}' ne obstaja")));
165 }
166 }
167 }
168
169 if napake.prazno() {
170 Ok(Zaporedje(funkcijski_klici).rc())
171 }
172 else {
173 Err(napake)
174 }
175 }
176
177 fn podpis_funkcije(ime: &Token, tipi: &[Tip]) -> String {
178 format!("{}({})", ime.as_str(), tipi.iter()
179 .map(|t| t.to_string())
180 .collect::<Vec<String>>()
181 .join(", "))
182 }
183}