slj/parser/
funkcija.rs

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            // imena parametrov, ločena z vejicami
42            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}